26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
54 #pragma package(smart_init)
73 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
74 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
75 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
76 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
77 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
78 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
89 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
90 AnsiString(TrainModeIn));
137 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
155 for(
int x = 0; x < 4; x++)
160 for(
int x = 0; x < 4; x++)
164 for(
int x = 0; x < 3; x++)
202 for(
int x = 0; x < 4; x++)
283 throw Exception(
"Error in attempting to delete FrontCodePtr");
287 for(
int x = 0; x < 4; x++)
291 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
296 for(
int x = 0; x < 4; x++)
300 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
335 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
401 bool TempDerail =
false;
447 else if((NextElementPosition > -1) && (NextEntryPos > -1))
518 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
528 for(
int x = 0; x < 4; x++)
535 for(
int x = 0; x < 4; x++)
802 int LockedVectorNumber;
931 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
932 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
933 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
934 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
935 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
936 "of a shortage of on train crew"};
952 int randval = random(10000);
957 if(randval < Utilities->MinorDelayCutoff)
964 if(randval < Utilities->ModerateDelayCutoff)
971 if(randval < Utilities->MajorDelayCutoff)
986 if(
NewDelay <
double(DwellTime) * 1440)
992 NewDelay -= double(DwellTime) * 1440;
1058 int randval2 = rand() % 24;
1059 AnsiString Reason = ReasonArray[randval2];
1062 " minutes because " + Reason);
1064 " minutes because " + Reason);
1070 " minutes because of a minor problem");
1072 " minutes because of a minor problem");
1238 if(BufferLocation ==
"")
1243 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1305 int NextElementPosition, NextEntryPos;
1329 NextElementPosition = -1;
1332 if((NextElementPosition > -1) && (NextEntryPos > -1))
1481 AnsiString StationName;
1492 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1502 if((NextElementPosition > -1) && (NextEntryPos > -1))
1653 if(TIFEntryPos == 0)
1690 if(NextElementPosition > -1)
1727 AnsiString Loc =
"";
1728 bool LocNamed =
false;
1757 Loc =
"outside railway";
1789 NextElementPosition = -1;
1800 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1818 if((NextElementPosition > -1) && (NextEntryPos > -1))
1856 FirstPair.second).
GetELink() == TempELink))
1861 SecondPair.second).
GetELink() == TempELink))
1875 FirstPair.second).
GetELink() == TempELink))
1880 SecondPair.second).
GetELink() == TempELink))
1894 FirstPair.second).
GetELink() == TempELink))
1899 SecondPair.second).
GetELink() == TempELink))
1929 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1932 int NewLastElement = 0, NewLastExitPos = 0;
1950 if(NewLastElement == -1)
1956 if(NewLastExitPos == -1)
1960 LastElement = NewLastElement;
1961 LastExitPos = NewLastExitPos;
1964 if(CumDistance < 1200)
1970 int FirstDistance = 0;
1971 if(CumDistance >= 1200)
1973 FirstDistance = 100;
1977 FirstDistance = 1200 - CumDistance;
1979 if(FirstDistance < 100)
1981 FirstDistance = 100;
2007 if(VectorIT->RouteNumber == RouteNumber)
2044 " failed when changing aspect.\nTrains can only pass under signaller control.");
2078 LockedVectorNumber)))
2237 for(
int x = 0; x < 4; x++)
2244 for(
int x = 0; x < 4; x++)
2270 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2275 if(OtherTrainEntryPos == -1)
2277 throw Exception(
"Error - OtherTrainEntryPos not set");
2296 int OtherTrainID = -1;
2297 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2388 bool StopRequired =
false;
2403 int NextElementEntryPos = -1;
2404 int NextElementExitPos = -1;
2405 bool TrainOnNextElement =
false;
2406 bool StopSignalAtNextElement =
false;
2407 if(ForwardConnection)
2415 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2417 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2478 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2542 int VPos, HPos, TrainHLocLead, TrainHLocMid, TrainHLocLag, TrainVLocLead, TrainVLocMid, TrainVLocLag;
2544 bool ReturnEarly =
false;
2577 int LeftHAndOffset, TopVAndOffset;
2582 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[0];
2583 if(((TrainLead.
HLoc * 16) +
HOffset[1]) < LeftHAndOffset)
2585 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[1];
2587 if(((TrainMid.
HLoc * 16) +
HOffset[2]) < LeftHAndOffset)
2589 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[2];
2591 if(((TrainMid.
HLoc * 16) +
HOffset[3]) < LeftHAndOffset)
2593 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[3];
2595 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[0];
2596 if(((TrainLead.
VLoc * 16) +
VOffset[1]) < TopVAndOffset)
2598 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[1];
2600 if(((TrainMid.
VLoc * 16) +
VOffset[2]) < TopVAndOffset)
2602 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[2];
2604 if(((TrainMid.
VLoc * 16) +
VOffset[3]) < TopVAndOffset)
2606 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[3];
2608 HPos = LeftHAndOffset;
2609 VPos = TopVAndOffset - 10;
2613 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[0];
2614 if(((TrainMid.
HLoc * 16) +
HOffset[1]) < LeftHAndOffset)
2616 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[1];
2618 if(((TrainMid.
HLoc * 16) +
HOffset[2]) < LeftHAndOffset)
2620 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[2];
2622 if(((TrainLag.
HLoc * 16) +
HOffset[3]) < LeftHAndOffset)
2624 LeftHAndOffset = (TrainLag.
HLoc * 16) +
HOffset[3];
2626 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[0];
2627 if(((TrainMid.
VLoc * 16) +
VOffset[1]) < TopVAndOffset)
2629 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[1];
2631 if(((TrainMid.
VLoc * 16) +
VOffset[2]) < TopVAndOffset)
2633 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[2];
2635 if(((TrainLag.
VLoc * 16) +
VOffset[3]) < TopVAndOffset)
2637 TopVAndOffset = (TrainLag.
VLoc * 16) +
VOffset[3];
2639 HPos = LeftHAndOffset;
2640 VPos = TopVAndOffset - 10;
2683 for(
int x = 3; x < 13; x++)
2688 for(
int y = 0; y < 54; y++)
2692 SLPtrOut[y] = SLPtrIn[y];
2693 SLPtrImage[y] = 0x01;
2717 for(
int x = 3; x < 13; x++)
2721 for(
int y = 0; y < 54; y++)
2753 Graphics::TBitmap *TempBitmap =
new Graphics::TBitmap;
2754 TempBitmap->PixelFormat = pf8bit;
2755 TempBitmap->Height = 10;
2756 TempBitmap->Width = 54;
2763 for(
int x = 0; x < 10; x++)
2765 SLPtrIn =
reinterpret_cast<Byte*
>(TempBitmap->ScanLine[x]);
2767 for(
int y = 0; y < 54; y++)
2769 if(SLPtrIn[y] == 0xac)
2773 else if(SLPtrIn[y] == 0xb4)
2777 else if(SLPtrIn[y] == 0x05)
2993 if(Code.Length() != 4)
2997 for(
int x = 1; x < 5; x++)
3004 for(
int x = 0; x < 4; x++)
3167 throw Exception(
"Error in GetOffsetValues - Link value wrong");
3180 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
3195 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
3204 TRect SourceRect, DestRect;
3206 DestRect.init(0, 0, 8, 8);
3209 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
3211 TempGraphic->PixelFormat = pf8bit;
3212 TempGraphic->Width = 16;
3213 TempGraphic->Height = 16;
3219 TempGraphic->Transparent =
true;
3223 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3224 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3230 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3238 else if(TempElement.
SpeedTag == 89)
3242 else if(TempElement.
SpeedTag == 90)
3246 else if(TempElement.
SpeedTag == 91)
3250 else if(TempElement.
SpeedTag == 92)
3254 else if(TempElement.
SpeedTag == 93)
3258 else if(TempElement.
SpeedTag == 94)
3262 else if(TempElement.
SpeedTag == 95)
3266 TempGraphic->Transparent =
true;
3270 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3271 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3273 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3280 for(
int x = 0; x < 40; x++)
3295 TempGraphic->Transparent =
true;
3299 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3300 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3302 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3316 TempGraphic->Transparent =
true;
3320 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3321 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3325 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
3328 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3333 TempGraphic->Transparent =
true;
3337 int BDVectorPos = -1;
3346 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3351 TempGraphic->Transparent =
true;
3355 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3356 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3358 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3364 TempGraphic->Transparent =
true;
3368 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3369 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3371 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3637 throw Exception(
"Error, same train on two different bridge tracks");
3683 AnsiString(EntryPos) +
"," +
HeadCode);
3700 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3719 AnsiString(EntryPos) +
"," +
HeadCode);
3728 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3761 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3762 int LockedVectorNumber;
3775 TRect SourceRect, DestRect;
3776 DestRect.init(0, 0, 8, 8);
3783 int FirstELink, SecondELink = -1;
3786 if(RoutePair2.first > -1)
3795 if(SecondELink == -1)
3797 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3802 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3812 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3813 DestGraphic->PixelFormat = pf8bit;
3814 DestGraphic->Width = 8;
3815 DestGraphic->Height = 8;
3816 DestGraphic->Transparent =
true;
3819 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3828 PrefDirElement, LockedVectorNumber))
3843 if(ElementEntryPos > 1)
3865 AnsiString(EntryPos) +
"," +
HeadCode);
3867 bool WrongRoute =
false;
3893 int LinkNumber = TrackElement.
Link[EntryPos];
3894 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3899 bool LogActionErrorCalled =
false;
3909 LogActionErrorCalled =
true;
3926 else if(LinkNumber == 3)
3934 LogActionErrorCalled =
true;
3951 else if(LinkNumber == 7)
3959 LogActionErrorCalled =
true;
3976 else if(LinkNumber == 9)
3984 LogActionErrorCalled =
true;
4016 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
4021 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
4031 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
4036 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
4045 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
4066 bool ColourError =
false, ColourError2 =
false;
4071 ColourError2 =
true;
4073 for(
int x = 0; x < 4; x++)
4078 ColourError2 =
true;
4084 "256 colours can be displayed");
4088 for(
int x = 0; x < 4; x++)
4175 AnsiString(EntryPos) +
"," +
HeadCode);
4176 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
4177 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
4178 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
4179 TrainInFrontInSignallerModeFlag =
false;
4180 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
4181 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
4182 bool SignallerStopRequired =
false;
4196 if(CurrentTrackVectorPosition > -1)
4200 if((EntryPos == 0) || (EntryPos == 2))
4213 else if(EntryPos == 1)
4237 EntryHalfLength = CurrentElementHalfLength;
4242 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
4246 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
4294 FrontElementMaxSpeed = LimitingSpeed;
4330 double ExitSpeedAtMaxBraking;
4335 ExitSpeedAtMaxBraking = 0;
4345 if(ExitSpeedAtMaxBraking > LimitingSpeed)
4347 SpeedToUse = ExitSpeedAtMaxBraking;
4351 SpeedToUse = LimitingSpeed;
4366 RedSignalFlag =
false;
4367 BuffersFlag =
false;
4368 StationFlag =
false;
4369 BuffersOrContinuationNowFlag =
false;
4370 ContinuationNextFlag =
false;
4373 CumulativeLength += (2 * CurrentElementHalfLength);
4376 SignallerStopRequired =
true;
4398 bool StopRequired =
false;
4414 StationFlag =
false;
4420 BuffersOrContinuationNowFlag =
true;
4422 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4426 if((EntryPos == 0) || (EntryPos == 2))
4448 if(NextTrackVectorPosition > -1)
4453 if((NextEntryPos == 0) || (NextEntryPos == 2))
4466 else if(NextEntryPos == 1)
4479 if(NextEntryPos > 1)
4493 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4505 RedSignalFlag =
true;
4526 TrainInFrontInSignallerModeFlag =
true;
4551 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4563 double MaxHalfSpeed;
4567 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4569 MaxHalfSpeed = FrontElementMaxSpeed;
4573 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4581 bool HalfSpeedLimited =
false;
4585 HalfSpeedLimited =
true;
4615 if(HalfSpeedLimited)
4640 if(SignallerStopRequired)
4656 int TempMaxExitSpeed;
4659 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4661 MaxExitSpeedAtHalfBraking = 0;
4665 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4669 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4671 TempMaxExitSpeed = FrontElementMaxSpeed;
4675 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4687 if(ExitSpeedHalfSquared < 10)
4697 if(ExitSpeedFullSquared < 10)
4769 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4770 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4794 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4795 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4805 if(!BuffersOrContinuationNowFlag)
4807 if(NextSpeedLimit < LimitingSpeed)
4809 LimitingSpeed = NextSpeedLimit;
4813 int TempMaxExitSpeed;
4817 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4819 MaxExitSpeedAtHalfBraking = 0;
4823 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4825 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4827 TempMaxExitSpeed = FrontElementMaxSpeed;
4831 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4842 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4855 if(!BuffersOrContinuationNowFlag)
4857 CurrentTrackVectorPosition = NextTrackVectorPosition;
4858 EntryPos = NextEntryPos;
4859 CurrentElementHalfLength = NextElementHalfLength;
4862 ContinuationNextFlag =
true;
4866 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4886 if(ExitSpeedHalfSquared < 10)
4896 if(ExitSpeedFullSquared < 10)
4959 double DeltaExitTimeToMaxInSecs;
4960 double DistanceToMax;
4969 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4971 DistanceToMax = EntryHalfLength;
4974 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4975 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4992 double DeltaExitTimeToMaxInSecs;
4993 double DistanceToMax;
5002 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
5004 DistanceToMax = EntryHalfLength / 2;
5007 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
5008 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
5019 if(ExitSpeedHalfSquared < 10)
5029 if(ExitSpeedFullSquared < 10)
5048 if((EntryPos == 0) || (EntryPos == 2))
5070 if(NextTrackVectorPosition > -1)
5072 int NextElementLength;
5073 if(NextEntryPos > 1)
5081 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
5277 int ElementCount = 0;
5285 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
5343 if((EntryPos == 0) || (EntryPos == 2))
5365 CurrentTrackVectorPosition = NextTrackVectorPosition;
5366 EntryPos = NextEntryPos;
5368 if(ElementCount > 1000)
5396 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5421 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5422 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5423 int RouteStartPosition;
5425 int PlatformPosition;
5427 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5443 if(Distance > (4000 + LeadElementDistance))
5466 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5469 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5515 if(!PlatformFoundFlag)
5517 PlatformPosition = CurrentTrackVectorPosition;
5520 PlatformFoundFlag =
true;
5536 if((EntryPos == 0) || (EntryPos == 2))
5580 if(ElementNumber < 2)
5582 SkipRouteCheck =
true;
5586 SkipRouteCheck =
false;
5588 if(ElementNumber == 1)
5590 RouteStartPosition = CurrentTrackVectorPosition;
5600 if(ElementNumber > 1)
5604 RouteOrPartRouteSet =
true;
5608 RouteOrPartRouteSet =
false;
5611 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5618 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5619 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5631 Distance += CurrentTrackElement.
Length01;
5635 Distance += CurrentTrackElement.
Length23;
5637 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5638 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5639 CurrentTrackVectorPosition = NextTrackVectorPosition;
5640 EntryPos = NextEntryPos;
5677 return(RepeatHeadCode);
5699 bool FrontValid =
false, RearValid =
false;
5700 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5704 TrainToBeJoinedBy = NULL;
5718 int TrainToBeJoinedByID = -1;
5739 if((TrainToBeJoinedByID < 0) && RearValid)
5758 if(TrainToBeJoinedByID < 0)
5760 TrainToBeJoinedBy = NULL;
5765 if(!TrainToBeJoinedBy->
Stopped())
5767 TrainToBeJoinedBy = NULL;
5777 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5778 TDateTime TimetableNonRepeatTime,
bool Warning)
5815 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5816 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5817 int IntMinsLate = 0;
5818 bool TTEvent =
false;
5823 ActionLog =
" arrived at ";
5833 ActionLog =
" terminated at ";
5839 ActionLog =
" departed from ";
5842 if(ActionType ==
Pass)
5844 ActionLog =
" passed ";
5849 ActionLog =
" created at ";
5851 if(ActionType ==
Enter)
5853 ActionLog =
" entered railway at ";
5857 ActionLog =
" changed its description to '" +
Description +
"' at ";
5865 if(ActionType ==
Leave)
5867 ActionLog =
" left railway at ";
5872 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5877 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5882 ActionLog =
" joined by ";
5887 ActionLog =
" changed direction at ";
5892 ActionLog =
" became new service ";
5897 ActionLog =
" taken under signaller control at ";
5901 ActionLog =
" restored to timetable control at ";
5907 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5911 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5915 ActionLog =
" REMOVED FROM RAILWAY at ";
5920 ActionLog =
" received signaller authority to proceed";
5924 ActionLog =
" received signaller authority to step forward";
5928 ActionLog =
" changed direction under signaller control at ";
5932 ActionLog =
" received signaller authority to pass stop signal";
5936 ActionLog =
" received signaller instruction to stop";
5940 ActionLog =
" stopped on signaller instruction ";
5944 ActionLog =
" joined under signaller control by ";
5948 ActionLog =
" suffered an onboard power failure at ";
5952 ActionLog =
" failure repaired at ";
5956 ActionLog =
" left railway under signaller control at ";
5958 if(OtherHeadCode !=
"")
5960 OtherHeadCode +=
" at ";
5992 bool TimePerformance =
true;
5993 AnsiString MinMinsString =
"";
6000 TimePerformance =
false;
6004 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
6006 if(ActionType ==
Pass)
6020 IntMinsLate = int(ceil(MinsLate));
6024 IntMinsLate = int(floor(MinsLate));
6026 if(IntMinsLate == 0)
6028 PerfLog =
" on time";
6030 else if(IntMinsLate == 1)
6032 PerfLog =
" 1 minute late";
6034 else if(IntMinsLate == -1)
6036 PerfLog =
" 1 minute early";
6038 else if(IntMinsLate > 1)
6040 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
6042 else if(IntMinsLate < -1)
6044 int PosIntMinsLate = -IntMinsLate;
6045 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
6047 if(LocationName.Pos(
'-') > 0)
6049 PerfLog =
"," + PerfLog;
6055 double MDT = int(MDTdouble * 10);
6057 MinMinsString =
"mins";
6058 if((MDT < 1.1) && (MDT > 0.9))
6060 MinMinsString =
"min";
6077 if(ReminderBaseLog !=
"")
6080 ReminderBaseLog =
"";
6084 if((ActionType ==
Arrive) && (IntMinsLate == 0))
6088 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
6093 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
6099 else if((ActionType ==
Pass) && (IntMinsLate == 0))
6103 else if((ActionType ==
Pass) && (IntMinsLate > 0))
6108 else if((ActionType ==
Pass) && (IntMinsLate < 0))
6114 else if((ActionType ==
Leave) && (IntMinsLate == 0))
6118 else if((ActionType ==
Leave) && (IntMinsLate > 0))
6123 else if((ActionType ==
Leave) && (IntMinsLate < 0))
6129 else if((ActionType ==
Depart) && (IntMinsLate == 0))
6133 else if((ActionType ==
Depart) && (IntMinsLate > 0))
6152 AnsiString LocName =
"";
6225 if(LocationName ==
"")
6229 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
6230 int FrontTrainRearPos, FrontTrainFrontPos;
6233 if(LocationName ==
"")
6235 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
6239 bool TemporaryDelay =
false;
6241 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6265 AnsiString SplittingTrainDescription =
Description;
6272 for(
int x = 0; x < 4; x++)
6292 double NewTrainPowerAtRail;
6298 NewTrainMass =
Mass * double(MassPercent)/100.0;
6300 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6301 if(NewTrainPowerAtRail == 0)
6303 NewTrainPowerAtRail = 0.08;
6311 NewTrainMass =
Mass;
6339 if(!SplitTrainExplicitDescription)
6386 if(LocationName ==
"")
6390 int RearTrainRearPos, RearTrainFrontPos;
6391 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
6394 if(LocationName ==
"")
6396 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6400 bool TemporaryDelay =
false;
6402 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6426 AnsiString SplittingTrainDescription =
Description;
6433 for(
int x = 0; x < 4; x++)
6453 double NewTrainPowerAtRail;
6459 NewTrainMass =
Mass * double(MassPercent)/100.0;
6461 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6462 if(NewTrainPowerAtRail == 0)
6464 NewTrainPowerAtRail = 0.08;
6472 NewTrainMass =
Mass;
6500 if(!SplitTrainExplicitDescription)
6594 TTrain *TrainToBeJoinedBy;
6638 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6640 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6704 int RouteNumber = -1;
6709 int CorrectRouteID = OR.
RouteID;
6715 bool FirstPass =
true;
6720 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6855 for(
int x = 0; x < IncNum; x++)
6888 else if(Ptr->
Command ==
"jbo")
6893 else if(Ptr->
Command ==
"dsc")
6898 else if(Ptr->
Command ==
"cms")
6909 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6915 bool IncludeFER =
false;
6923 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6928 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6939 else if(Ptr->
Command ==
"Fjo")
6945 else if(Ptr->
Command ==
"Frh")
6955 else if(Ptr->
Command ==
"Frh-sh")
7006 else if(Ptr->
Command ==
"jbo")
7011 else if(Ptr->
Command ==
"dsc")
7016 else if(Ptr->
Command ==
"cms")
7021 else if(Ptr->
Command ==
"cdt")
7029 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7451 int RouteNumber = -1;
7456 int CorrectRouteID = OR.
RouteID;
7462 bool FirstPass =
true;
7467 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7495 ",FloatingLabelNextString" +
"," +
HeadCode);
7496 AnsiString RetStr =
"", LocationName =
"";
7499 if(ActionTime == TDateTime(-1))
7503 if(ActionTime == TDateTime(-1))
7509 if(ActionTime != TDateTime(-1))
7517 throw Exception(
"Error - start entry in FloatingLabelNextString");
7561 else if(Ptr->
Command ==
"Fns")
7567 else if(Ptr->
Command ==
"F-nshs")
7598 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7600 else if(Ptr->
Command ==
"Frh")
7602 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7604 else if(Ptr->
Command ==
"Fer")
7606 AnsiString AllowedExits =
"";
7609 else if(Ptr->
Command ==
"Fjo")
7614 else if(Ptr->
Command ==
"jbo")
7619 else if(Ptr->
Command ==
"fsp")
7624 else if(Ptr->
Command ==
"rsp")
7629 else if(Ptr->
Command ==
"cdt")
7633 else if(Ptr->
Command ==
"dsc")
7637 else if(Ptr->
Command ==
"cms")
7646 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7690 else if(Ptr->
Command ==
"Fns")
7696 else if(Ptr->
Command ==
"F-nshs")
7727 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7729 else if(Ptr->
Command ==
"Frh")
7731 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7733 else if(Ptr->
Command ==
"Fer")
7735 AnsiString AllowedExits =
"";
7738 else if(Ptr->
Command ==
"Fjo")
7743 else if(Ptr->
Command ==
"jbo")
7748 else if(Ptr->
Command ==
"fsp")
7753 else if(Ptr->
Command ==
"rsp")
7758 else if(Ptr->
Command ==
"cdt")
7762 else if(Ptr->
Command ==
"dsc")
7766 else if(Ptr->
Command ==
"cms")
7775 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7819 else if(Ptr->
Command ==
"Fns")
7825 else if(Ptr->
Command ==
"F-nshs")
7856 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7858 else if(Ptr->
Command ==
"Frh")
7860 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7862 else if(Ptr->
Command ==
"Fer")
7864 AnsiString AllowedExits =
"";
7867 else if(Ptr->
Command ==
"Fjo")
7872 else if(Ptr->
Command ==
"jbo")
7877 else if(Ptr->
Command ==
"fsp")
7882 else if(Ptr->
Command ==
"rsp")
7887 else if(Ptr->
Command ==
"cdt")
7891 else if(Ptr->
Command ==
"dsc")
7895 else if(Ptr->
Command ==
"cms")
8039 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
8040 AnsiString DepTime =
"", EventTime =
"";
8041 bool CDTFlag =
false;
8043 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
8044 AnsiString TowardsLocation =
"";
8047 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
8049 TowardsLocation = AVI->LocationName;
8051 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
8060 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
8067 if(AVI->Command ==
"cdt")
8072 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
8087 RetStr +=
"\nNew service splits at approx. " + EventTime;
8091 if(AVI->Command ==
"jbo")
8110 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
8125 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
8129 if(AVI->Command ==
"Fjo")
8148 if(AVI->Command ==
"Frh")
8150 RetStr +=
"\nNew service finishes and remains at the location.";
8154 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
8161 if(TowardsLocation !=
"")
8163 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
8167 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
8172 if(TowardsLocation !=
"")
8174 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
8178 RetStr +=
"\nNew service departs at " + DepTime;
8187 if(TowardsLocation !=
"")
8189 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8193 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8198 if(TowardsLocation !=
"")
8200 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8204 RetStr +=
"\nNew service departs at approx. " + DepTime;
8221 if(TowardsLocation !=
"")
8223 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8227 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8232 if(TowardsLocation !=
"")
8234 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8238 RetStr +=
"\nNew service departs at approx. " + DepTime;
8257 ",FloatingTimetableString" +
"," +
HeadCode);
8258 AnsiString RetStr =
"", PartStr =
"";
8260 bool SkipDep =
false, SkipDepActedOn =
false;
8262 AnsiString MinMinsString =
"";
8267 throw Exception(
"Error - start entry in FloatingTimetableString");
8270 bool FirstPass =
true;
8276 AnsiString TrainLoc =
"";
8299 double MDT = int(MDTdouble * 10);
8301 MinMinsString =
"mins";
8302 if((MDT < 1.1) && (MDT > 0.9))
8304 MinMinsString =
"min";
8318 double MDT = int(MDTdouble * 10);
8320 MinMinsString =
"mins";
8321 if((MDT < 1.1) && (MDT > 0.9))
8323 MinMinsString =
"min";
8351 double MDT = int(MDTdouble * 10);
8353 MinMinsString =
"mins";
8354 if((MDT < 1.1) && (MDT > 0.9))
8356 MinMinsString =
"min";
8370 double MDT = int(MDTdouble * 10);
8372 MinMinsString =
"mins";
8373 if((MDT < 1.1) && (MDT > 0.9))
8375 MinMinsString =
"min";
8391 AnsiString TrainLoc =
"";
8405 double MDT = int(MDTdouble * 10);
8407 MinMinsString =
"mins";
8408 if((MDT < 1.1) && (MDT > 0.9))
8410 MinMinsString =
"min";
8424 double MDT = int(MDTdouble * 10);
8426 MinMinsString =
"mins";
8427 if((MDT < 1.1) && (MDT > 0.9))
8429 MinMinsString =
"min";
8447 double MDT = int(MDTdouble * 10);
8449 MinMinsString =
"mins";
8450 if((MDT < 1.1) && (MDT > 0.9))
8452 MinMinsString =
"min";
8478 else if(Ptr->
Command ==
"Fns")
8484 else if(Ptr->
Command ==
"F-nshs")
8517 else if(Ptr->
Command ==
"Frh")
8521 else if(Ptr->
Command ==
"Fer")
8523 AnsiString AllowedExits =
"";
8526 else if(Ptr->
Command ==
"Fjo")
8531 else if(Ptr->
Command ==
"jbo")
8536 else if(Ptr->
Command ==
"fsp")
8546 PartStr+=
", split mass%-Power% = 50-50";
8549 else if(Ptr->
Command ==
"rsp")
8559 PartStr+=
", split mass%-Power% = 50-50";
8562 else if(Ptr->
Command ==
"cdt")
8566 else if(Ptr->
Command ==
"dsc")
8570 else if(Ptr->
Command ==
"cms")
8576 RetStr = RetStr +
'\n' + PartStr;
8590 SkipDepActedOn =
true;
8601 RetStr =
"Timetable finished";
8605 RetStr =
"No timetable";
8609 return(
"Timetable:\n" + RetStr);
8762 bool ForwardHeadCode;
8766 ForwardHeadCode =
true;
8771 ForwardHeadCode =
false;
8914 if(ColourNumber == 0)
8918 else if(ColourNumber == 1)
8922 else if(ColourNumber == 2)
8926 else if(ColourNumber == 3)
8930 else if(ColourNumber == 4)
8934 else if(ColourNumber == 5)
8938 else if(ColourNumber == 6)
8942 else if(ColourNumber == 7)
8946 else if(ColourNumber == 8)
8950 else if(ColourNumber == 9)
8954 else if(ColourNumber == 10)
8958 else if(ColourNumber == 11)
8962 else if(ColourNumber == 12)
8966 else if(ColourNumber == 13)
8970 else if(ColourNumber == 14)
8982 for(
int x = 0; x < 4; x++)
8989 for(
int x = 0; x < 4; x++)
9074 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
9077 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
9078 bool GiveMessagesFalse =
false;
9079 bool CheckLocationsExistInRailwayTrue =
true;
9086 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
9089 if(Marker[6] ==
'1')
9554 bool HideFlashingTrain =
true;
9557 Graphics::TBitmap *SmallTrainBitmap;
9598 HideFlashingTrain =
false;
9603 HideFlashingTrain =
false;
9608 HideFlashingTrain =
false;
9613 HideFlashingTrain =
false;
9618 HideFlashingTrain =
false;
9622 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9626 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9650 for(
int y = 0; y < 3; y++)
9654 bool FoundFlag =
false;
9665 if(IMPair.first != IMPair.second)
9692 if((LocationName ==
"") && (
MidElement > -1))
9696 if((LocationName ==
"") && (
LagElement > -1))
9700 if(LocationName ==
"")
9702 throw Exception(
"Error - Location name not set in TrainAtLocation");
9713 for(
int x = 0; x < 4; x++)
9726 for(
int x = 0; x < 4; x++)
9747 AnsiString(LinkNumber) +
"," +
HeadCode);
9799 int DistanceToRedSignal = 0, DistanceToExit = -1;
9800 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9804 float MinsEarly = 0;
9805 TDateTime DepartureTime;
9806 TDateTime ArrivalTime;
9834 if(TempTTE < LastTimeToExit)
9869 if(TempTTE < LastTimeToExit)
9892 if(TempTTE < LastTimeToExit)
9922 if(TempTTE < LastTimeToExit)
9945 if(TempTTE < LastTimeToExit)
9988 float CurrentStopTime;
9989 float LaterStopTime;
9990 float RecoverableTime;
9998 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
10005 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
10006 bool DistanceToExitSet = (DistanceToExit > -1);
10007 int GenericDistance = DistanceToRedSignal;
10008 if(DistanceToExitSet)
10010 GenericDistance = DistanceToExit;
10026 float TimeToSubtract, TotalStopTime;
10029 TimeToSubtract = RecoverableTime;
10072 if(CurrentStopTime > 0)
10074 TotalStopTime = CurrentStopTime + LaterStopTime;
10083 else if((MinsEarly > 0) && !
Stopped())
10085 TotalStopTime = LaterStopTime + MinsEarly;
10089 if(LaterStopTime == 0)
10091 TotalStopTime = CurrentStopTime;
10097 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
10100 if(AvTrackSpeed < 30)
10104 int Speed = AvTrackSpeed;
10114 if(DistanceToRedSignalSet)
10116 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
10126 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
10155 if((NextEntryPos == 0) || (NextEntryPos == 2))
10313 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10352 if(AVEntry0.
Command ==
"Snt")
10356 int IncrementalMinutes = 0;
10357 int IncrementalDigits = 0;
10365 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
10401 if(AVEntry0.
Command ==
"Snt-sh")
10406 int IncrementalMinutes = 0;
10407 int IncrementalDigits = 0;
10415 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
10459 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10539 AnsiString Loc =
"";
10540 bool ElementFound =
false;
10545 ElementFound =
true;
10550 ElementFound =
true;
10555 ElementFound =
true;
10584 else if(AVEntryPtr->
Command ==
"Fer")
10586 bool CorrectExit =
false;
10593 CorrectExit =
true;
10698 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10716 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10731 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10742 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10743 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10744 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10746 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10747 "," + AnsiString(Mass) +
"," + ModeStr);
10749 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10751 int RearExitPos = -1;
10753 for(
int x = 0; x < 4; x++)
10760 if(RearExitPos == -1)
10762 throw Exception(
"Error, RearExit == -1 in AddTrain");
10764 bool ReportFlag =
true;
10769 ReportFlag =
false;
10781 if(ModeStr ==
"Timetable")
10787 if(MaxRunningSpeed < 10)
10789 MaxRunningSpeed = 10;
10791 if(SignallerSpeed < 10)
10793 SignallerSpeed = 10;
10795 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10796 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10803 if(SignallerControl)
10833 if(!SignallerControl)
10848 if(!SignallerControl)
10859 AnsiString Loc =
"";
10876 if(!SignallerControl)
10895 int RouteNumber = -1;
10896 bool SignalsSet =
false;
10903 int RouteStartPosition;
10907 if(FirstPair.first == RouteNumber)
10909 RouteStartPosition = FirstPair.second;
10911 else if(SecondPair.first == RouteNumber)
10913 RouteStartPosition = SecondPair.second;
10917 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10923 else if(RouteNumber > -1)
10943 int LinkedRouteNumber = -1;
10964 int RouteStartPosition;
10968 if(FirstPair.first == RouteNumber)
10970 RouteStartPosition = FirstPair.second;
10972 else if(SecondPair.first == RouteNumber)
10974 RouteStartPosition = SecondPair.second;
10978 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10984 else if(RouteNumber > -1)
11004 int LinkedRouteNumber = -1;
11025 AnsiString(TrackVectorNumber));
11028 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
11037 throw Exception(
"Error, VecPos not set in EntryPos");
11039 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
11044 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
11049 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
11063 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
11071 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
11081 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
11102 return(RepeatTime);
11111 AnsiString RetStr =
"", PartStr =
"", MinMinsString;
11119 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
11127 if(Ptr->SignallerControl)
11129 RetStr =
"Train under signaller control";
11134 if(Ptr->ArrivalTime == Ptr->DepartureTime)
11136 if(Ptr->MinDwellTime > 30.1)
11138 double MDTdouble = Ptr->MinDwellTime / 60;
11139 double MDT = int(MDTdouble * 10);
11141 MinMinsString =
"mins";
11142 if((MDT < 1.1) && (MDT > 0.9))
11144 MinMinsString =
"min";
11155 if(Ptr->MinDwellTime > 30.1)
11157 double MDTdouble = Ptr->MinDwellTime / 60;
11158 double MDT = int(MDTdouble * 10);
11160 MinMinsString =
"mins";
11161 if((MDT < 1.1) && (MDT > 0.9))
11163 MinMinsString =
"min";
11176 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
11178 if(Ptr->MinDwellTime > 30.1)
11180 double MDTdouble = Ptr->MinDwellTime / 60;
11181 double MDT = int(MDTdouble * 10);
11183 MinMinsString =
"mins";
11184 if((MDT < 1.1) && (MDT > 0.9))
11186 MinMinsString =
"min";
11195 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
11199 else if(Ptr->FormatType ==
PassTime)
11203 else if(Ptr->Command ==
"Fns")
11209 else if(Ptr->Command ==
"F-nshs")
11212 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
11219 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
11226 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
11229 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
11232 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
11239 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
11241 PartStr =
"Terminate at " + Ptr->LocationName;
11243 else if(Ptr->Command ==
"Frh")
11245 PartStr =
"Terminate at " + Ptr->LocationName;
11247 else if(Ptr->Command ==
"Fer")
11249 AnsiString AllowedExits;
11253 else if(Ptr->Command ==
"Fjo")
11256 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
11258 else if(Ptr->Command ==
"jbo")
11261 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
11263 else if(Ptr->Command ==
"fsp")
11268 else if(Ptr->Command ==
"rsp")
11273 else if(Ptr->Command ==
"cdt")
11277 else if(Ptr->Command ==
"dsc")
11281 else if(Ptr->Command ==
"cms")
11287 RetStr = RetStr +
'\n' + PartStr;
11295 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
11306 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
11309 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
11310 AnsiString DepTime =
"", EventTime =
"";
11311 bool CDTFlag =
false;
11313 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
11314 AnsiString TowardsLocation =
"";
11317 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
11319 TowardsLocation = AVI->LocationName;
11321 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
11330 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
11336 if(AVI->Command ==
"cdt")
11338 CDTFlag = !CDTFlag;
11341 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
11344 RetStr +=
"\nNew service splits at " + EventTime;
11348 if(AVI->Command ==
"jbo")
11351 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
11355 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
11358 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
11362 if(AVI->Command ==
"Fjo")
11365 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
11369 if(AVI->Command ==
"Frh")
11371 RetStr +=
"\nNew service finishes and remains at location.";
11375 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
11380 if(TowardsLocation !=
"")
11382 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
11386 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
11391 if(TowardsLocation !=
"")
11393 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
11397 RetStr +=
"\nNew service departs at " + DepTime;
11566 ActiveTrackElementNameMapEntry.second = 0;
11572 std::ifstream TTBLFile(FileName, std::ios_base::binary);
11575 if(TTBLFile.is_open())
11577 char *TrainTimetableString =
new char[10000];
11579 bool EndOfFile =
false;
11582 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11584 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11591 delete[] TrainTimetableString;
11595 AnsiString OneLine(TrainTimetableString);
11596 bool FinalCallFalse =
false;
11597 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11601 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11602 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11607 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
11609 delete[] TrainTimetableString;
11613 OneLine = AnsiString(TrainTimetableString);
11619 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11621 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11631 OneLine = AnsiString(TrainTimetableString);
11633 if(OneLine.Length() > 9999)
11635 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11637 delete[] TrainTimetableString;
11641 bool FinalCallFalse =
false;
11642 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11646 delete[] TrainTimetableString;
11650 if(EndOfFile && (Count < 2))
11653 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11655 delete[] TrainTimetableString;
11661 delete[] TrainTimetableString;
11666 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11677 bool CheckLocationsExistInRailway)
11807 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11817 if(OneLine[1] !=
'*')
11819 int DelimPos = OneLine.Pos(
';');
11820 int CPos = OneLine.Pos(
',');
11821 if((CPos > 0) && (CPos < DelimPos))
11836 bool AllCommas =
true;
11838 for(
int x = 1; x < OneLine.Length() + 1; x++)
11840 if(OneLine[x] !=
',')
11845 if(AllCommas || (OneLine ==
""))
11860 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11861 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11862 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11863 TDateTime StartTime(0);
11865 bool Warning =
false;
11892 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11893 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11894 double MaxBrakeRate = 0;
11895 double PowerAtRail = 0;
11896 int SignallerSpeed = 0;
11897 if(OneLine[1] ==
'*')
11903 int Pos = OneLine.Pos(
',');
11906 int SubStringLength = 20;
11907 if(OneLine.Length() < 20)
11909 SubStringLength = OneLine.Length();
11911 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11915 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11916 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11927 TempTrainDataEntry.
HeadCode = HeadCode;
11931 if(Description !=
"")
11936 TempTrainDataEntry.
Mass = Mass;
11944 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11947 while(NewRemainder[NewRemainder.Length()] ==
',')
11949 if(NewRemainder.Length() > 1)
11951 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11960 if(NewRemainder ==
"")
11962 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11967 int CommaCount = 0;
11968 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11970 if(NewRemainder[x] ==
',')
11975 if(CommaCount == 0)
11977 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11979 int SubStringLength = 20;
11980 if(OneLine.Length() < 20)
11982 SubStringLength = OneLine.Length();
11985 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11986 OneLine.SubString(1, SubStringLength) +
"'....");
11991 AnsiString OneEntry =
"";
11996 bool FinishFlag =
false;
11998 for(
int x = 0; x < CommaCount + 1; x++)
12000 if((CommaCount == 0) || (x < CommaCount))
12005 if(CommaCount == 0)
12007 OneEntry = NewRemainder;
12012 Pos = NewRemainder.Pos(
',');
12013 OneEntry = NewRemainder.SubString(1, Pos - 1);
12014 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
12020 RearStartOrRepeatMins = 0;
12021 FrontStartOrRepeatDigits = 0;
12022 NumberOfRepeats = 0;
12023 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
12024 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
12026 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
12037 if(Warning && (Second ==
"Frh"))
12039 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
12043 if(Warning && (Second ==
"Fjo"))
12046 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
12083 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
12087 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
12089 if(NewRemainder[1] !=
'R')
12092 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
12098 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12102 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
12105 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
12111 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
12116 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
12121 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
12124 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
12140 TDateTime TempTime;
12146 ActionVectorEntry.
Warning = Warning;
12169 ActionVectorEntry.
Command = Second;
12192 else if(FormatType ==
TimeCmd)
12198 ActionVectorEntry.
Command = Second;
12206 ActionVectorEntry.
Command = Second;
12207 ActionVectorEntry.
ExitList = ExitList;
12215 ActionVectorEntry.
Command = Second;
12229 ActionVectorEntry.
Command = Second;
12240 ActionVectorEntry.
Command = Second;
12250 ActionVectorEntry.
Command = Second;
12252 if((Second ==
"fsp") || (Second ==
"rsp"))
12267 ActionVectorEntry.
Command = Second;
12276 ActionVectorEntry.
Command = Second;
12282 ActionVectorEntry.
Command = Second;
12290 ActionVectorEntry.
Command = Second;
12299 ActionVectorEntry.
Command = Second;
12302 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12307 OneEntry = NewRemainder;
12312 RearStartOrRepeatMins = 0;
12313 FrontStartOrRepeatDigits = 0;
12314 NumberOfRepeats = 0;
12315 if((FinishFlag) && (OneEntry[1] !=
'R'))
12318 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
12322 if(OneEntry[1] !=
'R')
12324 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
12325 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
12327 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'.\nIf the program version is not the latest the "
12328 "timetable may have features that aren't compatible with the version in use.");
12345 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
12352 TDateTime TempTime;
12358 ActionVectorEntry.
Warning = Warning;
12365 ActionVectorEntry.
Command = Second;
12373 ActionVectorEntry.
Command = Second;
12382 ActionVectorEntry.
Command = Second;
12391 ActionVectorEntry.
Command = Second;
12401 ActionVectorEntry.
Command = Second;
12402 ActionVectorEntry.
ExitList = ExitList;
12406 ActionVectorEntry.
Command = Second;
12408 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12413 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
12429 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12448 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
12453 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
12468 if(TimeStr.Length() < 5)
12473 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
12478 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
12483 if(TimeStr[3] !=
':')
12488 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
12493 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
12498 while(TimeStr.Length() > 5)
12500 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
12502 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
12503 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
12505 if((WholeHours + FracHour) >= 95.98334)
12510 Time = TDateTime((WholeHours + FracHour) / 24);
12517 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
12518 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
12527 TDateTime TempTime;
12529 if(OneEntry.Length() > 0)
12531 if(OneEntry[1] ==
'W')
12534 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
12538 if(OneEntry ==
"Frh")
12548 if(OneEntry.Length() < 7)
12553 int Pos = OneEntry.Pos(
';');
12561 First = OneEntry.SubString(1, 5);
12567 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
12570 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
12573 if(Remainder.Length() < 7)
12578 Pos = Remainder.Pos(
';');
12585 Second = Remainder.SubString(1, 5);
12591 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12592 Pos = Third.Pos(
';');
12595 Fourth = Third.SubString(Pos + 1, Remainder.Length() - Pos);
12601 Third = Third.SubString(1, Pos - 1);
12602 for(
int x = 1; x <= Fourth.Length(); x++)
12604 if((Fourth[x] <
'0') || (Fourth[x] >
'9'))
12606 TimetableMessage(GiveMessages,
"Invalid character in minimum dwell time in " + OneEntry +
". Must be a whole number of seconds.");
12611 if(Fourth.ToDouble() < 29.9)
12613 TimetableMessage(GiveMessages,
"Error in timetable - a minimum dwell time can't be less than 30 seconds: '" + OneEntry +
"'");
12630 Pos = Remainder.Pos(
';');
12633 Second = Remainder;
12634 if(Second ==
"cdt")
12659 if((Pos != 0) && (
CheckLocationValidity(4, Remainder.SubString(1, Pos - 1),
false, CheckLocationsExistInRailway)))
12661 Second = Remainder.SubString(1, Pos - 1);
12664 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12670 for(
int x = 1; x <= Third.Length(); x++)
12672 if((Third[x] <
'0') || (Third[x] >
'9'))
12674 TimetableMessage(GiveMessages,
"Invalid character in minimum dwell time in " + OneEntry +
". Must be a whole number of seconds.");
12679 if(Third.ToDouble() < 29.9)
12681 TimetableMessage(GiveMessages,
"Error in timetable - a minimum dwell time can't be less than 30 seconds: '" + OneEntry +
"'");
12694 if((Pos != 4) && (Pos != 7) && (Pos != 8))
12700 Second = Remainder.SubString(1, Pos - 1);
12702 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12704 Pos = Remainder.Pos(
';');
12711 Third = Remainder.SubString(1, Pos - 1);
12712 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12715 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12718 int SpacePos = Third.Pos(
' ');
12724 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
12725 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
12727 if(CheckLocationsExistInRailway)
12737 if(Second ==
"Snt")
12760 if(Second ==
"Sns-sh")
12779 if(Second ==
"F-nshs")
12793 if(Second ==
"Sns-fsh")
12807 if(Second ==
"Fns-sh")
12827 if(Second ==
"pas")
12842 if(Second ==
"Fer")
12849 if(CheckLocationsExistInRailway)
12860 if(Second ==
"dsc")
12862 if(Third.Length() > 60)
12864 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12868 for(
int x = 1; x < Third.Length() + 1; x++)
12871 if((Third[x] <
' ') && (Third[x] >= 0))
12873 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12885 if(Second ==
"cms")
12893 for(
int x = 1; x < Third.Length() + 1; x++)
12895 if((Third[x] <
'0') || (Third[x] >
'9'))
12897 TimetableMessage(GiveMessages,
"Train maximum speed must be a number in '" + Third +
"'");
12902 int MaxRunningSpeed = Third.ToInt();
12905 TimetableMessage(GiveMessages,
"Train maximum running speed [" + Third +
"km/h] can't be greater than 400km/h");
12909 if(MaxRunningSpeed < 10)
12912 TimetableMessage(GiveMessages,
"Train maximum running speed [" + Third +
"km/h] can't be less than 10km/h.");
12927 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12928 (Second !=
"Frh-sh"))
12940 if(Second ==
"Frh-sh")
12948 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12952 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12956 if((Second ==
"Sfs") || (Second ==
"Sns"))
12961 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12978 if((Text ==
"Snt") || (Text ==
"Sfs") || (Text ==
"Sns") || (Text ==
"Sns-fsh") || (Text ==
"Snt-sh") || (Text ==
"Sns-sh") ||
12979 (Text ==
"pas") || (Text ==
"jbo") || (Text ==
"fsp") || (Text ==
"rsp") || (Text ==
"cdt") || (Text ==
"dsc") ||
12980 (Text ==
"cms") || (Text ==
"Fns") || (Text ==
"Fjo") || (Text ==
"Fer") || (Text ==
"Frh-sh") || (Text ==
"Fns-sh") ||
12981 (Text ==
"F-nshs") || (Text ==
"Frh"))
12995 bool ErrorFlag =
false;
12997 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
13001 int pos = SplitDistributionString.Pos(
'-');
13008 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
13009 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
13012 int x = MassStr.ToInt();
13013 int y = PowerStr.ToInt();
13014 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
13019 catch(
const Exception &e)
13026 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
13027 "power for the new split-off train");
13048 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
13053 for(
int x = 1; x < LocStr.Length() + 1; x++)
13055 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
13069 if(CheckLocationsExistInRailway)
13074 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
13075 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
13076 "that includes a continuation will not be valid.");
13094 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
13097 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
13102 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
13104 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
13106 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
13112 for(
int x = 3; x >= 0; x--)
13114 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
13115 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
13117 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
13133 AnsiString CurrentID =
"";
13135 if(IDSet.Length() == 0)
13137 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
13141 for(
int x = 1; x <= IDSet.Length(); x++)
13144 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
13146 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
13168 int Pos = IDSet.Pos(
' ');
13179 CurrentID = IDSet.SubString(1, Pos - 1);
13180 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
13192 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
13199 if(!ExitList.empty())
13201 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
13203 if(*ELIT == VecPos)
13205 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
13212 ExitList.push_back(VecPos);
13222 Pos = IDSet.Pos(
' ');
13229 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
13236 AnsiString Remainder =
"";
13237 int SemiColonCount = 0;
13239 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
13241 if(TrainInfoStr[x] ==
';')
13246 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
13248 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
13249 "'. Should be headcode + optional description for a continuing service;" +
13250 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
13254 if(SemiColonCount == 0)
13256 HeadCode = TrainInfoStr;
13265 if(SemiColonCount == 1)
13267 Pos = TrainInfoStr.Pos(
';');
13268 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
13269 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
13275 if(Description ==
"")
13277 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
13281 if(Description.Length() > 60)
13283 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
13287 for(
int x = 1; x < Description.Length() + 1; x++)
13290 if((Description[x] <
' ') && (Description[x] >= 0))
13292 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
13301 Pos = TrainInfoStr.Pos(
';');
13302 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
13303 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
13309 Pos = Remainder.Pos(
';');
13310 Description = Remainder.SubString(1, Pos - 1);
13311 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13312 if(Description ==
"")
13314 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
13318 if(Description.Length() > 60)
13320 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
13324 for(
int x = 1; x < Description.Length() + 1; x++)
13327 if((Description[x] <
' ') && (Description[x] >= 0))
13329 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
13334 Pos = Remainder.Pos(
';');
13335 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
13337 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13338 if(StartSpeedStr ==
"")
13340 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
13344 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
13346 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
13348 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
13353 StartSpeed = StartSpeedStr.ToInt();
13359 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13363 Pos = Remainder.Pos(
';');
13364 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
13366 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13367 if(MaxRunningSpeedStr ==
"")
13369 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
13373 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
13375 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
13377 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
13382 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
13385 TimetableMessage(GiveMessages,
"Train maximum running speed [" + MaxRunningSpeedStr +
"km/h] can't be greater than 400km/h");
13389 if(MaxRunningSpeed < 10)
13392 TimetableMessage(GiveMessages,
"Train maximum running speed [" + MaxRunningSpeedStr +
"km/h] can't be less than 10km/h.");
13396 Pos = Remainder.Pos(
';');
13397 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
13399 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13402 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
13406 for(
int x = 1; x < MassStr.Length() + 1; x++)
13408 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
13410 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
13415 Mass = MassStr.ToInt() * 1000;
13421 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
13427 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
13431 Pos = Remainder.Pos(
';');
13432 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
13434 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13435 if(MaxBrakeForceStr ==
"")
13437 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
13441 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
13443 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
13445 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
13450 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
13453 if((MaxBrakeForce / Mass) > 1)
13455 MaxBrakeForce = Mass;
13458 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
13462 if((MaxBrakeForce / Mass) < 0.01)
13464 MaxBrakeForce = Mass * 0.01;
13467 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
13472 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
13474 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
13476 if(SemiColonCount == 6)
13478 GrossPowerStr = Remainder;
13479 SignallerSpeedStr =
"30";
13483 Pos = Remainder.Pos(
';');
13484 GrossPowerStr = Remainder.SubString(1, Pos - 1);
13485 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13488 if(GrossPowerStr ==
"")
13490 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
13494 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
13496 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
13498 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
13504 double GrossPower = GrossPowerStr.ToInt() * 1000;
13511 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
13515 else if(GrossPower == 0)
13520 else if((GrossPower > 0) && (GrossPower < 10000))
13523 GrossPower = 10000;
13525 PowerAtRail = GrossPower * 0.8;
13529 if(SignallerSpeedStr ==
"")
13531 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
13535 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
13537 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
13539 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
13544 SignallerSpeed = SignallerSpeedStr.ToInt();
13550 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13554 if(SignallerSpeed < 10)
13557 SignallerSpeed = 10;
13560 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
13578 if(OneEntry.Length() < 7)
13580 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13584 int SemiColonCount = 0;
13586 for(
int x = 1; x < OneEntry.Length() + 1; x++)
13588 if(OneEntry[x] ==
';')
13593 if(SemiColonCount != 3)
13595 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13599 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
13601 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13605 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
13610 Pos = Remainder.Pos(
';');
13611 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
13613 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13614 if(MinutesStr ==
"")
13616 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
13620 if(MinutesStr.Length() > 3)
13623 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
13627 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
13629 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
13631 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
13636 RearStartOrRepeatMins = MinutesStr.ToInt();
13637 if(RearStartOrRepeatMins == 0)
13639 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
13643 Pos = Remainder.Pos(
';');
13644 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
13646 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13647 if(DigitsStr ==
"")
13649 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
13653 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
13655 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
13657 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
13662 if(DigitsStr.Length() > 2)
13664 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
13668 FrontStartOrRepeatDigits = DigitsStr.ToInt();
13682 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
13686 AnsiString NumberStr = Remainder;
13688 if(NumberStr ==
"")
13690 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
13694 if(NumberStr.Length() > 4)
13697 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
13701 for(
int x = 1; x < NumberStr.Length() + 1; x++)
13703 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
13706 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
13711 NumberOfRepeats = NumberStr.ToInt();
13712 if(NumberOfRepeats == 0)
13714 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13991 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
14012 TwoLocationFlag =
false;
14018 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
14032 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
14048 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
14060 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
14086 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
14099 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
14100 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
14101 "location of any other type of finish.");
14107 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
14113 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
14114 "event for: " + TDEntry.
HeadCode);
14124 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14129 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
14139 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14144 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
14154 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14165 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
14175 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
14187 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14194 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
14203 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
14222 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
14224 AnsiString LocationName =
"";
14238 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
14239 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
14248 if(AVEntry0.
Command ==
"Snt-sh")
14262 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
14278 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
14279 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
14291 bool FoundFlag =
false;
14295 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
14297 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14309 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
14322 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14347 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14369 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14391 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14416 bool LocFoundFlag, FnsFoundFlag;
14420 LocFoundFlag =
false;
14421 FnsFoundFlag =
false;
14422 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
14427 FnsFoundFlag =
true;
14436 LocFoundFlag =
true;
14447 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
14448 "by an event at the same location that has an identified location name, normally an arrival, see "
14455 if(FnsFoundFlag && !LocFoundFlag)
14457 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
14458 "by an event at the same location that has an identified location name, normally an arrival, see "
14472 if(AVEntry0.
Command ==
"Sns")
14484 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
14492 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
14493 ". The event isn't valid for a stationary train.");
14501 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
14508 TDateTime SnsEventTime = AVEntry0.
EventTime;
14511 bool BreakFlag =
false;
14514 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
14519 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
14541 if(AVEntry0.
Command ==
"Sfs")
14543 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14551 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
14563 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14568 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14588 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14595 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14610 if(AVEntry0.
Command ==
"Sfs")
14622 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
14630 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
14631 ". The event isn't valid for a stationary train.");
14639 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
14646 TDateTime SfsEventTime = AVEntry0.
EventTime;
14648 bool BreakFlag =
false;
14651 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
14656 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
14676 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14681 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14702 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14709 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14714 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
14717 "Please make sure that the finish event of the service that links to this event is preceded by an "
14718 "event at the same location that has an identified location name, normally an arrival.");
14723 else if(AVEntry.
Command ==
"Snt-sh")
14726 "Please make sure that the service starts with zero speed and is at a named location.");
14731 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
14734 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
14741 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14754 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14764 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
14771 if(AVEntry.
Command ==
"F-nshs")
14776 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14804 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14805 ". The event isn't valid for a stationary train.");
14815 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14823 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14824 ". The event isn't valid for a stationary train.");
14842 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14843 ". The event isn't valid for a stationary train.");
14861 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14862 ". The event isn't valid for a stationary train.");
14880 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cms' is followed by an illegal event for: " + TDEntry.
HeadCode +
14881 ". The event isn't valid for a stationary train.");
14891 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14899 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14900 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14935 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14936 ". The event isn't valid for a moving train.");
14958 bool LastEntryIsAnArrival =
false;
14965 LastEntryIsAnArrival =
false;
14966 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14973 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14975 if(LastEntryIsAnArrival)
14979 LastEntryIsAnArrival =
false;
15003 SecondPassMessage(GiveMessages,
"Error in timetable - a minimum dwell time is not permitted for a departure, "
15004 "add it to the corresponding arrival instead, see: " + TDEntry.
HeadCode);
15016 LastEntryIsAnArrival =
true;
15023 LastEntryIsAnArrival =
true;
15024 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15031 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
15033 if(LastEntryIsAnArrival)
15037 LastEntryIsAnArrival =
false;
15040 SecondPassMessage(GiveMessages,
"Error in timetable - a minimum dwell time is not permitted for a departure, "
15041 "add it to the corresponding arrival instead, see: " + TDEntry.
HeadCode);
15051 LastEntryIsAnArrival =
true;
15061 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15069 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
15077 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
15078 ". The event isn't valid for a stationary train.");
15089 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
15097 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
15098 ". The event isn't valid for a moving train.");
15112 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15119 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
15123 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
15130 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
15134 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
15143 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
15147 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
15154 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
15165 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15180 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
15188 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
15203 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
15215 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
15227 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
15228 ", may be before timetable start time");
15239 AnsiString LastLocationName =
"";
15243 bool LastEntryIsAnArrival =
false;
15248 LastEntryIsAnArrival =
false;
15249 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
15250 if(LastLocationName !=
"")
15252 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
15254 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
15267 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
15279 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
15292 TwoLocationFlag =
true;
15297 LastEntryIsAnArrival =
false;
15301 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
15304 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
15309 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
15312 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
15318 LastEntryIsAnArrival = !LastEntryIsAnArrival;
15324 LastEntryIsAnArrival =
true;
15325 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
15326 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15338 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
15350 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
15363 TwoLocationFlag =
true;
15368 LastEntryIsAnArrival =
false;
15372 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
15375 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
15383 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
15390 LastEntryIsAnArrival = !LastEntryIsAnArrival;
15398 AnsiString LocationNameToBeChecked =
"";
15403 unsigned int y = 0;
15417 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
15418 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
15436 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
15445 TwoLocationFlag =
true;
15456 if(TwoLocationFlag)
15466 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15471 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
15473 AnsiString LocName =
"";
15479 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
15486 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
15509 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15534 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15556 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15578 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15597 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15600 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
15615 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15620 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
15624 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
15628 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
15632 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
15671 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15673 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
15679 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
15692 int IncMinutes = 0;
15702 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15708 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
15714 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
15719 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15725 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
15730 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15743 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15777 if(HeadCode.Length() > 4)
15779 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
15790 int ForwardCount = 0;
15791 int ReverseCount = 0;
15793 if(MainHeadCode == SecondHeadCode)
15795 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
15804 if(TDEntry.
HeadCode == MainHeadCode)
15806 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15821 if(ForwardCount == 0)
15824 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
15826 if(ForwardCount > 2)
15829 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
15830 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15839 if(TDEntry.
HeadCode == SecondHeadCode)
15841 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15856 if(ReverseCount == 0)
15858 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15863 if(ReverseCount > 2)
15866 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15867 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15872 if(ForwardCount != ReverseCount)
15874 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15875 " than the other way round");
15906 int ForwardCount = 0;
15907 int ReverseCount = 0;
15908 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15917 if(TDEntry.
HeadCode == MainHeadCode)
15919 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15922 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15927 ForwardEntryPtr = &AVEntry;
15929 ForwardTDVectorNumber = x;
15932 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15933 (AVEntry.
Command ==
"Frh-sh")))
15938 ForwardEntryPtr = &AVEntry;
15940 ForwardTDVectorNumber = x;
15946 if(ForwardCount == 0)
15949 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15951 if(ForwardCount > 1)
15953 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15963 if(TDEntry.
HeadCode == OtherHeadCode)
15965 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15968 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15974 ReverseEntryPtr = &AVEntry;
15975 ReverseTDVectorNumber = x;
15978 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15984 ReverseEntryPtr = &AVEntry;
15985 ReverseTDVectorNumber = x;
15992 if(ReverseCount == 0)
15994 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15999 if(ReverseCount > 1)
16001 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16008 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
16009 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
16010 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
16011 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
16015 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
16022 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
16027 if(SetDataAndCheckLocations)
16029 if(ForwardEntryPtr->LocationName ==
"")
16031 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
16032 ". One or other service does not have a location set");
16039 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
16040 ". One or other service does not have a location set");
16045 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16047 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
16048 " is at a different location to the referencing train " + MainHeadCode);
16057 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16059 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
16060 " has a different event time to the referencing train " + MainHeadCode);
16068 if(ForwardShuttleStart && ReverseShuttleFinish)
16073 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
16074 " first repeat restart time not consistent with finish service " + OtherHeadCode);
16080 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
16083 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16085 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
16086 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
16092 if(ReverseEntryPtr->
Command ==
"Fjo")
16095 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16097 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
16098 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
16104 if(ReverseEntryPtr->
Command ==
"Fns")
16107 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16109 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
16110 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
16116 if(ForwardEntryPtr->Command ==
"Sfs")
16118 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
16121 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
16128 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
16130 if(ReverseEntryPtr->
Command !=
"Sfs")
16132 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
16140 if(SetDataAndCheckLocations)
16144 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
16151 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
16157 bool StationLocation =
false;
16160 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
16164 StationLocation =
true;
16168 if(StationLocation)
16172 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
16182 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
16188 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16200 if(ForwardEntryPtr->Command ==
"Sns")
16202 if(ReverseEntryPtr->
Command !=
"Fns")
16204 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
16205 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
16211 if(ForwardEntryPtr->Command ==
"Fns")
16213 if(ReverseEntryPtr->
Command !=
"Sns")
16215 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
16216 " and forms a new service with headcode " + OtherHeadCode);
16223 if(SetDataAndCheckLocations)
16225 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16237 if(ForwardEntryPtr->Command ==
"jbo")
16239 if(ReverseEntryPtr->
Command !=
"Fjo")
16241 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
16242 " and is joined by a train with headcode " + OtherHeadCode);
16248 if(ForwardEntryPtr->Command ==
"Fjo")
16250 if(ReverseEntryPtr->
Command !=
"jbo")
16252 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
16253 " and joins a train with headcode " + OtherHeadCode);
16260 if(SetDataAndCheckLocations)
16262 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16278 if(ForwardShuttleStart)
16281 if(!ReverseShuttleFinish)
16284 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
16285 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
16291 if(ReverseShuttleStart)
16294 if(!ForwardShuttleFinish)
16297 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
16298 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
16305 if(SetDataAndCheckLocations)
16307 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16320 bool MainRepeat =
false, OtherRepeat =
false;
16330 OtherRepeat =
true;
16333 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
16335 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
16336 " and the associated train with headcode " + OtherHeadCode);
16341 if(MainRepeat && OtherRepeat)
16347 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
16348 " and the associated train with headcode " + OtherHeadCode);
16370 while(Input[1] ==
' ')
16372 if(Input.Length() > 1)
16374 Input = Input.SubString(2, Input.Length() - 1);
16388 while(Input[Input.Length()] ==
' ')
16390 if(Input.Length() > 1)
16392 Input = Input.SubString(1, Input.Length() - 1);
16402 AnsiString Output =
"";
16403 bool DelimiterFound =
false;
16405 for(
int x = 1; x < Input.Length() + 1; x++)
16409 if(Input[x] ==
' ')
16414 if((Input[x] !=
',') && (Input[x] !=
';'))
16416 DelimiterFound =
false;
16417 Output = Output + Input[x];
16421 DelimiterFound =
true;
16422 Output = Output + Input[x];
16434 DelimiterFound =
false;
16435 for(
int x = Input.Length(); x > 0; x--)
16439 if(Input[x] ==
' ')
16444 if((Input[x] !=
',') && (Input[x] !=
';'))
16446 DelimiterFound =
false;
16447 Output = AnsiString(Input[x]) + Output;
16451 DelimiterFound =
true;
16452 Output = AnsiString(Input[x]) + Output;
16477 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
16479 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
16491 LocationName = LocRear;
16495 LocationName = LocFront;
16497 if(LocationName ==
"")
16518 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
16559 int RearPosition = 0, FrontPosition = 0;
16562 if(RearPosition < 0)
16569 if(FrontPosition < 0)
16581 for(
int x = 0; x < 4; x++)
16583 if(RearTrackElement.
Conn[x] == FrontPosition)
16598 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
16605 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
16611 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
16642 AnsiString(RearExitPos));
16653 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
16655 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
16658 AnsiString RearName, FrontName;
16674 FrontName = FrontTrackElement.
ElementID;
16677 int LockedVectorNumber;
16797 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
16802 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
16810 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
16815 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
16849 "," + AnsiString(IncDigits));
16852 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16857 return(BaseHeadCode);
16859 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16860 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16862 while(NextRepeatDigits >= 100)
16864 NextRepeatDigits -= 100;
16866 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16868 if(NextRepeatDigitsStr.Length() < 2)
16870 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16872 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16875 return(NextRepeatHeadCode);
16883 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16884 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16886 return(NextRepeatTime);
16895 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16896 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16897 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16898 int RepeatSecs = RepeatMinutes * 60;
16900 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16934 NonRepeatingHeadCode);
16935 int ForwardCount = 0;
16936 int ReverseCount = 0;
16937 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16947 if(TDEntry.
HeadCode == MainHeadCode)
16949 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16955 ForwardEntryPtr = &AVEntry;
16957 ForwardTDVectorNumber = x;
16962 if(ForwardCount == 0)
16965 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16967 if(ForwardCount > 1)
16969 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16979 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16981 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16988 ReverseEntryPtr = &AVEntry;
16989 ReverseTDVectorNumber = x;
16995 if(ReverseCount == 0)
16997 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
17002 if(ReverseCount > 1)
17004 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
17005 NonRepeatingHeadCode);
17010 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
17012 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
17017 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
17019 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
17024 if(SetDataAndCheckLocations)
17026 if(ForwardEntryPtr->LocationName ==
"")
17028 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
17029 ". One or other service does not have a location set");
17036 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
17037 ". One or other service does not have a location set");
17042 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
17044 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
17045 " is at a different location to the referencing train " + MainHeadCode);
17051 if(ForwardEntryPtr->Command ==
"F-nshs")
17054 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
17056 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
17057 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
17063 if(ForwardEntryPtr->Command ==
"Fns-sh")
17067 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
17069 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
17070 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
17076 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
17079 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
17081 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
17082 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
17100 if(ForwardEntryPtr->Command ==
"Sns-sh")
17102 if(ReverseEntryPtr->
Command !=
"F-nshs")
17104 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
17105 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
17111 if(ForwardEntryPtr->Command ==
"F-nshs")
17113 if(ReverseEntryPtr->
Command !=
"Sns-sh")
17115 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
17116 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
17123 if(SetDataAndCheckLocations)
17125 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
17137 if(ForwardEntryPtr->Command ==
"Sns-fsh")
17139 if(ReverseEntryPtr->
Command !=
"Fns-sh")
17142 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
17143 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
17149 if(ForwardEntryPtr->Command ==
"Fns-sh")
17151 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
17154 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
17155 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
17162 if(SetDataAndCheckLocations)
17164 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
17188 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
17189 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
17190 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
17191 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
17193 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
17217 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
17220 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
17221 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
17223 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
17225 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
17230 while(LastActionCommand ==
"Fns")
17232 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
17233 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
17234 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
17237 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
17238 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
17245 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
17248 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
17249 ". The linking of two or more shuttles is not permitted.");
17269 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
17287 ShowMessage(Message);
17296 int Mins = Input, Hrs = 0;
17302 AnsiString AnsiMins = AnsiString(Mins);
17303 if(AnsiMins.Length() == 1)
17305 AnsiMins =
"0" + AnsiMins;
17307 AnsiString AnsiHrs = AnsiString(Hrs);
17308 if(AnsiHrs.Length() == 1)
17310 AnsiHrs =
"0" + AnsiHrs;
17313 return(AnsiHrs +
':' + AnsiMins);
17357 AnsiString(ActionEventType) +
"," + LocationID);
17358 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
17363 Prefix =
" ERROR: ";
17366 Prefix =
" HELD: ";
17367 ErrorLog =
" can't enter railway, train obstructing entry position ";
17368 WarningStr =
" can't enter railway, train obstructing entry position ";
17373 Prefix =
" HELD: ";
17374 ErrorLog =
" can't enter railway, route set against it at entry position ";
17375 WarningStr =
" can't enter railway, route set against it at entry position ";
17380 Prefix =
" HELD: ";
17381 ErrorLog =
" can't be created, train obstructing at ";
17382 WarningStr =
" can't be created, train obstructing at ";
17387 Prefix =
" HELD: ";
17388 ErrorLog =
" can't be created on a locked route at ";
17389 WarningStr =
" can't be created on a locked route at ";
17394 Prefix =
" HELD: ";
17395 ErrorLog =
" can't enter on a locked route at ";
17396 WarningStr =
" can't enter on a locked route at ";
17401 Prefix =
" HELD: ";
17402 ErrorLog =
" can't be created, points set wrongly at ";
17403 WarningStr =
" can't be created, points set wrongly at ";
17408 ErrorLog =
" left railway unexpectedly at ";
17413 ErrorLog =
" left railway at an incorrect exit at ";
17418 ErrorLog =
" failed to split - location too short at ";
17419 WarningStr =
" failed to split, location too short at ";
17424 Prefix =
" HELD: ";
17425 ErrorLog =
" unable to split - other train obstructing at ";
17426 WarningStr =
" unable to split - other train obstructing at ";
17431 ErrorLog =
" stopped at buffers unexpectedly at position ";
17435 ErrorLog =
" failed to stop at ";
17440 ErrorLog =
" failed to split at ";
17445 ErrorLog =
" failed to be joined by other train at ";
17450 ErrorLog =
" failed to change its description at ";
17455 ErrorLog =
" failed to change its maximum speed at ";
17460 ErrorLog =
" failed to join other train at ";
17465 ErrorLog =
" failed to terminate at ";
17470 ErrorLog =
" failed to form new service at ";
17475 ErrorLog =
" failed to exit railway ";
17480 ErrorLog =
" failed to change direction at ";
17485 ErrorLog =
" failed to pass ";
17490 ErrorLog =
" facing buffers and unable to start at ";
17494 ErrorLog =
" DERAILED at position ";
17495 Prefix =
" DERAILMENT: ";
17500 ErrorLog =
" CRASHED INTO BUFFERS at ";
17501 Prefix =
" CRASH: ";
17506 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
17507 Prefix =
" CRASH: ";
17512 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
17513 Prefix =
" CRASH: ";
17517 else if(ActionEventType ==
FailSPAD)
17519 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
17520 Prefix =
" SPAD: ";
17525 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
17526 Prefix =
" SPAD RISK: ";
17531 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
17535 Prefix =
" WARNING: ";
17536 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
17537 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
17542 Prefix =
" WARNING: ";
17543 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
17544 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
17549 Prefix =
" WARNING: ";
17550 ErrorLog =
" is without power so it can't depart from ";
17551 WarningStr =
" is without power so it can't depart from ";
17556 Prefix =
" WARNING: ";
17557 ErrorLog =
" can't depart because there is a train in front at ";
17558 WarningStr =
" can't depart because there is a train in front at ";
17596 std::ofstream OutFile(
"TrainData.csv");
17600 ShowMessage(
"Output file TrainData.csv failed to open");
17607 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
17612 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
17613 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
17614 "RepeatNumber" <<
'\n' <<
'\n';
17615 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
17618 AnsiString TimetableEntryTypeStr;
17624 TimetableEntryTypeStr =
"NoFormat";
17630 TimetableEntryTypeStr =
"TimeLoc";
17636 TimetableEntryTypeStr =
"TimeTimeLoc";
17642 TimetableEntryTypeStr =
"TimeCmd";
17648 TimetableEntryTypeStr =
"StartNew";
17654 TimetableEntryTypeStr =
"TimeCmdHeadCode";
17660 TimetableEntryTypeStr =
"FinRemHere";
17666 TimetableEntryTypeStr =
"FNSShuttle";
17672 TimetableEntryTypeStr =
"SNTShuttle";
17678 TimetableEntryTypeStr =
"SNSShuttle";
17684 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
17690 TimetableEntryTypeStr =
"FSHNewService";
17696 TimetableEntryTypeStr =
"Repeat";
17702 TimetableEntryTypeStr =
"Default";
17713 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
17714 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
17717 AnsiString RunningEntryStr;
17723 RunningEntryStr =
"NotStarted";
17729 RunningEntryStr =
"Running";
17735 RunningEntryStr =
"Exited";
17739 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
17756 ShowMessage(Message);
17757 BaseTime = TDateTime::CurrentDateTime();
17771 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17784 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17786 for(
int x = 0; x < NumberOfTrains; x++)
17788 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17808 int NumberOfTrains;
17815 for(
int x = 0; x < NumberOfTrains; x++)
17852 for(
int x = 0; x < LockedRouteVectorSize; x++)
17859 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17870 int LockedRouteVectorSize;
17877 for(
int x = 0; x < LockedRouteVectorSize; x++)
17935 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17943 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17954 int ContinuationAutoSigVectorSize;
17961 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
18031 if(AVFirstEntry.
Command ==
"Snt")
18055 CTEMMP.second = CTEEntry;
18062 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
18070 CTEMMP.second = CTEEntry;
18091 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
18108 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
18110 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
18121 AnsiString RetStr =
"", PartStr =
"";
18236 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18240 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18242 AnsiString ShortTTName =
"";
18244 for(
int x = TTFileName.Length(); x > 0; x--)
18246 if(TTFileName[x] ==
'\\')
18248 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
18253 ShowMessage(
"Creates two timetables named " + ShortTTName +
18254 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
18256 Screen->Cursor = TCursor(-11);
18258 AnsiString FormatNoDPStr =
"#######0";
18259 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
18262 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
18269 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
18271 if(TrainDataEntry.
Mass > 0)
18273 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
18277 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
18281 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
18285 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
18287 FirstHeadCode = TrainDataEntry.
HeadCode;
18288 int IncDigits = 0, IncMinutes = 0;
18290 if(!ActionVector.empty())
18292 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18294 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
18295 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18313 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18318 AnsiString PartStr =
"", TimeStr =
"";
18335 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
18339 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
18349 PartStr =
"Enters at " + LocName;
18362 PartStr =
"Created at " + LocName;
18376 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
18381 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
18387 else if(ActionVectorEntry.
Command ==
"Sfs")
18389 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
18393 else if(ActionVectorEntry.
Command ==
"Sns")
18395 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18403 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18409 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
18417 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18420 AnsiString FirstHeadCode = TDE->
HeadCode;
18424 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
18436 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
18438 OneTTEntry.
Action = PartStr;
18439 OneTTEntry.
Time = TimeStr;
18441 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
18446 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
18452 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
18457 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
18465 else if(ActionVectorEntry.
Command ==
"jbo")
18467 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
18471 else if(ActionVectorEntry.
Command ==
"fsp")
18475 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
18479 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
18484 else if(ActionVectorEntry.
Command ==
"rsp")
18488 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
18492 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
18497 else if(ActionVectorEntry.
Command ==
"cdt")
18499 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
18502 else if(ActionVectorEntry.
Command ==
"dsc")
18504 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
18507 else if(ActionVectorEntry.
Command ==
"cms")
18509 PartStr =
"Change maximum speed to " + ActionVectorEntry.
NewMaxSpeed +
" at " + ActionVectorEntry.
LocationName;
18515 if(ActionVectorEntry.
Command ==
"Fns")
18517 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18521 else if(ActionVectorEntry.
Command ==
"F-nshs")
18523 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18529 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
18536 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18542 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18549 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
18554 else if(ActionVectorEntry.
Command ==
"Frh")
18556 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
18561 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18565 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18575 else if(ActionVectorEntry.
Command ==
"Fer")
18577 AnsiString AllowedExits;
18581 else if(ActionVectorEntry.
Command ==
"Fjo")
18583 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
18592 OneTTEntry.
Action = PartStr;
18593 OneTTEntry.
Time = TimeStr;
18600 AllTTTrains->push_back(OneTTLine);
18604 std::ofstream TTFile(TTFileName.c_str());
18608 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
18609 delete AllTTTrains;
18644 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
18645 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
18647 TTFile << AllTTTrains->at(x).Header.c_str();
18650 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18652 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
18654 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
18658 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
18661 TTFile <<
'\n' <<
'\n';
18663 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
18665 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
18666 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18668 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
18670 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
18674 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
18679 TTFile <<
'\n' <<
'\n';
18684 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18686 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
18688 std::ofstream TTFile2(TTFileName2.c_str());
18692 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
18693 delete AllTTTrains;
18697 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
18698 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
18699 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
18701 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
18706 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
18707 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
18709 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18711 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
18713 bool GiveMessagesFalse =
false;
18714 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
18715 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
18716 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
18721 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
18722 TimeString = TimeString.SubString(9, 5);
18723 ActionString +=
" " + OtherHeadCode;
18725 if(TimeString.SubString(1, 7) ==
"End at ")
18728 TimeString = TimeString.SubString(8, 5);
18730 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
18731 AnsiMultiMapEntry.first = TimeString;
18732 AnsiMultiMapEntry.second = OneLine;
18733 TAMM->insert(AnsiMultiMapEntry);
18738 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
18740 TTFile2 << (AMMIT->second).c_str();
18742 delete AllTTTrains;
18751 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
18755 bool AnalysisError =
false;
18756 AnsiString SequenceLog =
"SequenceLog\n";
18799 TTrainDataVector::iterator TDVIt, TDVCopyIt;
18801 int IteratorNumber = 0;
18802 AnsiString AnsiSuffix =
"";
18809 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
18812 AnsiSuffix = AnsiString(Suffix);
18813 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
18814 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
18820 int Increment = 0, SlashPos;
18822 AnsiString LinkedHeadCode;
18826 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
18828 if(AVEIt->LinkedTrainEntryPtr != NULL)
18837 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18839 if(LinkedHeadCode[x] ==
'/')
18841 SlashPos = LinkedHeadCode.Length() - x + 1;
18844 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18845 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18846 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18852 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18856 AVEIt->OtherHeadCode =
"";
18858 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
18860 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
18864 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18867 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18869 if(LinkedHeadCode[x] ==
'/')
18871 SlashPos = LinkedHeadCode.Length() - x + 1;
18874 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18875 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18876 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18882 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18886 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18891 SequenceLog +=
"1\n";
18894 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18900 ServiceCallingLocsList.clear();
18901 if(ActionVector.empty())
18905 if(ActionVector.at(0).SignallerControl)
18909 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18927 int HLoc = TE.
HLoc;
18928 int VLoc = TE.
VLoc;
18929 AnsiString HString;
18930 AnsiString VString;
18933 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18937 HString = AnsiString(HLoc);
18941 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18945 VString = AnsiString(VLoc);
18947 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18970 else if(AVE.
Command ==
"cdt")
18983 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18992 ServiceCallingLocsList.push_back(LName);
18996 int HLoc = TE.
HLoc;
18997 int VLoc = TE.
VLoc;
18998 AnsiString HString;
18999 AnsiString VString;
19002 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19006 HString = AnsiString(HLoc);
19010 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19014 VString = AnsiString(VLoc);
19016 ServiceCallingLocsList.push_back(HString +
'-' + VString);
19020 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
19024 SequenceLog +=
"2\n";
19053 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
19059 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
19060 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
19061 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
19063 SequenceLog +=
"3\n";
19070 TDateTime LastTDTime;
19071 int IncMinutes = 0;
19073 if(ActionVector.empty())
19077 if(ActionVector.at(0).SignallerControl)
19081 if(AVLast->FormatType ==
Repeat)
19083 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
19091 if(AVLast->ArrivalTime != TDateTime(-1))
19093 LastTDTime = AVLast->ArrivalTime;
19095 else if(AVLast->EventTime != TDateTime(-1))
19097 LastTDTime = AVLast->EventTime;
19116 SequenceLog +=
"4\n";
19153 int IncMinutes = 0;
19155 if(ActionVector.empty())
19159 if(ActionVector.at(0).SignallerControl)
19163 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
19165 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
19167 for(
int y = 0; y < NumTrains; y++)
19181 for(
unsigned int z = 0; z < ActionVector.size(); z++)
19196 LocServiceTimesVector.push_back(TLSTEntry);
19199 AnsiString IncTime =
"", FoundStopTime =
"";
19200 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
19202 if(ActionVector.at(a).FormatType ==
TimeLoc)
19213 if(FoundStopTime ==
"")
19215 throw Exception(
"Failure to determine FoundStopTime for located Snt");
19217 int WhileCount = 0;
19226 if(IncTime >= FoundStopTime)
19230 LocServiceTimesVector.push_back(TLSTEntry);
19231 if(WhileCount > 2000)
19233 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
19246 int HLoc = TE.
HLoc;
19247 int VLoc = TE.
VLoc;
19248 AnsiString HString;
19249 AnsiString VString;
19252 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19256 HString = AnsiString(HLoc);
19260 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19264 VString = AnsiString(VLoc);
19266 TLSTEntry.
Location = HString +
'-' + VString;
19270 LocServiceTimesVector.push_back(TLSTEntry);
19278 LocServiceTimesVector.push_back(TLSTEntry);
19280 AnsiString IncTime =
"", FoundStopTime =
"";
19281 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
19283 if(ActionVector.at(a).FormatType ==
TimeLoc)
19294 if(FoundStopTime ==
"")
19296 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
19298 int WhileCount = 0;
19307 if(IncTime >= FoundStopTime)
19311 LocServiceTimesVector.push_back(TLSTEntry);
19312 if(WhileCount > 2000)
19314 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
19324 bool SkipAddingMinutes =
false;
19327 LocServiceTimesVector.push_back(TLSTEntry);
19329 AnsiString IncTime =
"", FoundStopTime =
"";
19330 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
19332 if(ActionVector.at(a).FormatType ==
TimeLoc)
19340 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
19344 LocServiceTimesVector.pop_back();
19345 SkipAddingMinutes =
true;
19350 if(FoundStopTime ==
"")
19352 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
19354 if(!SkipAddingMinutes)
19356 int WhileCount = 0;
19365 if(IncTime >= FoundStopTime)
19369 LocServiceTimesVector.push_back(TLSTEntry);
19370 if(WhileCount > 2000)
19372 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
19381 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
19383 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
19385 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
19386 LocServiceTimesVector.pop_back();
19387 LocServiceTimesVector.push_back(TLSTEntry);
19392 LocServiceTimesVector.push_back(TLSTEntry);
19398 LocServiceTimesVector.push_back(TLSTEntry);
19417 LocServiceTimesVector.push_back(TLSTEntry);
19421 AnsiString TempDepTime = TLSTEntry.
DepTime;
19423 LocServiceTimesVector.push_back(TLSTEntry);
19425 while(TLSTEntry.
AtLocTime < TempDepTime)
19430 TLSTEntry.
DepTime = TempDepTime;
19431 LocServiceTimesVector.push_back(TLSTEntry);
19435 LocServiceTimesVector.push_back(TLSTEntry);
19446 LocServiceTimesVector.push_back(TLSTEntry);
19449 LocServiceTimesVector.push_back(TLSTEntry);
19469 AnsiString HString;
19470 AnsiString VString;
19473 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19477 HString = AnsiString(HLoc);
19481 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19485 VString = AnsiString(VLoc);
19487 TLSTEntry.
Location = HString +
'-' + VString;
19489 LocServiceTimesVector.push_back(TLSTEntry);
19494 AnsiString FrhTime;
19495 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
19499 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
19507 LocServiceTimesVector.push_back(TLSTEntry);
19513 LocServiceTimesVector.push_back(TLSTEntry);
19518 else if(AVE.
Command ==
"Frh-sh")
19520 if(y == NumTrains - 1)
19526 LocServiceTimesVector.push_back(TLSTEntry);
19532 LocServiceTimesVector.push_back(TLSTEntry);
19545 SequenceLog +=
"5\n";
19578 TLocServiceTimesVector::iterator Ptr1, Ptr2;
19581 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
19582 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
19584 std::ofstream TTFile3(TTFileName3.c_str());
19588 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
19592 if(LocServiceTimesVector.empty())
19594 ShowMessage(
"No timetabled services found");
19596 DeleteFile(TTFileName3);
19600 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
19601 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
19602 SequenceLog +=
"6\n";
19831 Ptr1 = LocServiceTimesVector.begin();
19833 while(Ptr2 != LocServiceTimesVector.end())
19835 while(Ptr2->Location == Ptr1->Location)
19838 if(Ptr2 == LocServiceTimesVector.end())
19845 if(Ptr2 != LocServiceTimesVector.end())
19853 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
19854 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19855 MinuteString =
" minutes";
19856 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19859 MinuteString =
" minute";
19861 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
19862 TTFile3 <<
",Platforms,Trains\n\n";
19864 Ptr1 = LocServiceTimesVector.begin();
19866 while(Ptr2 != LocServiceTimesVector.end())
19868 PreviousService =
"";
19869 NumTrainsAtLoc = 0;
19870 ServiceAndRepeatNumTotal =
"";
19872 NumPlatsAtThisLocCalculated =
false;
19874 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19876 PreviousService =
"";
19877 NumTrainsAtLoc = 0;
19878 ServiceAndRepeatNumTotal =
"";
19880 NumPlatsAtThisLocCalculated =
false;
19884 if(Ptr2 == LocServiceTimesVector.end())
19889 if(Ptr2 == LocServiceTimesVector.end())
19893 while(Ptr2->Location == Ptr1->Location)
19895 PreviousService =
"";
19896 NumTrainsAtLoc = 0;
19897 ServiceAndRepeatNumTotal =
"";
19898 BasicTime = Ptr1->ArrTime;
19899 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19903 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19905 BasicTime = Ptr2->ArrTime;
19908 if(Ptr2 == LocServiceTimesVector.end())
19912 if(Ptr2->Location != Ptr1->Location)
19917 if(Ptr2 == LocServiceTimesVector.end())
19921 if(Ptr2->Location != Ptr1->Location)
19927 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19931 if(!NumPlatsAtThisLocCalculated)
19934 NumPlatsAtThisLocCalculated =
true;
19936 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19938 if(ServiceAndRepeatNumTotal ==
"")
19940 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19941 NumTrainsAtLoc = 1;
19945 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19948 PreviousService = Ptr2->ServiceAndRepeatNum;
19949 if(ServiceAndRepeatNumTotal ==
"")
19951 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19952 NumTrainsAtLoc = 1;
19956 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19960 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19962 int MaxNumberOfSameDirections = 0;
19963 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19968 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19972 AnsiString Asterisk =
"";
19973 if(MaxNumberOfSameDirections >= NumPlats)
19978 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19979 ArrivalsPrinted =
true;
19980 ServiceAndRepeatNumTotal =
"";
19982 if(Ptr2 == LocServiceTimesVector.end())
19986 if(Ptr2->Location != Ptr1->Location)
19991 if(Ptr2 == LocServiceTimesVector.end())
19997 if(!ArrivalsPrinted)
19999 TTFile3 <<
"Nothing to report for arrivals";
20004 SequenceLog +=
"7\n";
20009 Ptr1 = LocServiceTimesVector.begin();
20011 while(Ptr2 != LocServiceTimesVector.end())
20013 while(Ptr2->Location == Ptr1->Location)
20016 if(Ptr2 == LocServiceTimesVector.end())
20023 if(Ptr2 != LocServiceTimesVector.end())
20030 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
20031 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
20032 MinuteString =
" minutes";
20033 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
20036 MinuteString =
" minute";
20038 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
20039 TTFile3 <<
",Platforms,Trains\n\n";
20041 Ptr1 = LocServiceTimesVector.begin();
20043 while(Ptr2 != LocServiceTimesVector.end())
20045 PreviousService =
"";
20046 NumTrainsAtLoc = 0;
20047 ServiceAndRepeatNumTotal =
"";
20049 NumPlatsAtThisLocCalculated =
false;
20051 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
20053 PreviousService =
"";
20054 NumTrainsAtLoc = 0;
20055 ServiceAndRepeatNumTotal =
"";
20057 NumPlatsAtThisLocCalculated =
false;
20061 if(Ptr2 == LocServiceTimesVector.end())
20066 if(Ptr2 == LocServiceTimesVector.end())
20070 while(Ptr2->Location == Ptr1->Location)
20072 PreviousService =
"";
20073 NumTrainsAtLoc = 0;
20074 ServiceAndRepeatNumTotal =
"";
20075 BasicTime = Ptr1->DepTime;
20076 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
20080 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
20082 BasicTime = Ptr2->DepTime;
20085 if(Ptr2 == LocServiceTimesVector.end())
20089 if(Ptr2->Location != Ptr1->Location)
20094 if(Ptr2 == LocServiceTimesVector.end())
20098 if(Ptr2->Location != Ptr1->Location)
20104 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
20108 if(!NumPlatsAtThisLocCalculated)
20111 NumPlatsAtThisLocCalculated =
true;
20113 if(Ptr1->ServiceAndRepeatNum != PreviousService)
20115 if(ServiceAndRepeatNumTotal ==
"")
20117 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
20118 NumTrainsAtLoc = 1;
20122 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
20125 PreviousService = Ptr2->ServiceAndRepeatNum;
20126 if(ServiceAndRepeatNumTotal ==
"")
20128 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
20129 NumTrainsAtLoc = 1;
20133 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
20137 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
20139 int MaxNumberOfSameDirections = 0;
20140 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
20145 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
20149 AnsiString Asterisk =
"";
20150 if(MaxNumberOfSameDirections >= NumPlats)
20155 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
20156 DeparturesPrinted =
true;
20157 ServiceAndRepeatNumTotal =
"";
20159 if(Ptr2 == LocServiceTimesVector.end())
20163 if(Ptr2->Location != Ptr1->Location)
20168 if(Ptr2 == LocServiceTimesVector.end())
20174 if(!DeparturesPrinted)
20176 TTFile3 <<
"Nothing to report for departures";
20181 SequenceLog +=
"8\n";
20188 Ptr1 = LocServiceTimesVector.begin();
20190 while(Ptr2 != LocServiceTimesVector.end())
20192 while(Ptr2->Location == Ptr1->Location)
20195 if(Ptr2 == LocServiceTimesVector.end())
20202 if(Ptr2 != LocServiceTimesVector.end())
20209 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
20210 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
20211 TTFile3 <<
",Platforms,Trains,\n\n";
20212 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
20213 Ptr1 = LocServiceTimesVector.begin();
20215 while(Ptr2 != LocServiceTimesVector.end())
20217 PreviousService =
"";
20218 ServiceAndRepeatNumTotal =
"";
20219 NumTrainsAtLoc = 0;
20221 NumPlatsAtThisLocCalculated =
false;
20224 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
20226 PreviousService =
"";
20227 ServiceAndRepeatNumTotal =
"";
20228 NumTrainsAtLoc = 0;
20230 NumPlatsAtThisLocCalculated =
false;
20234 if(Ptr2 == LocServiceTimesVector.end())
20239 if(Ptr2 == LocServiceTimesVector.end())
20243 while(Ptr2->Location == Ptr1->Location)
20245 if(Ptr1->FrhMarker ==
"Frh")
20248 Ptr1->FrhMarker =
"FrhCounted";
20250 PreviousService =
"";
20251 NumTrainsAtLoc = 0;
20252 ServiceAndRepeatNumTotal =
"";
20253 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
20257 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
20260 if(Ptr1->FrhMarker ==
"Frh")
20263 Ptr1->FrhMarker =
"FrhCounted";
20266 if(Ptr2 == LocServiceTimesVector.end())
20270 if(Ptr2->Location != Ptr1->Location)
20275 if(Ptr2 == LocServiceTimesVector.end())
20279 if(Ptr2->Location != Ptr1->Location)
20283 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
20285 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
20289 if(!NumPlatsAtThisLocCalculated)
20292 NumPlatsAtThisLocCalculated =
true;
20294 if(Ptr1->ServiceAndRepeatNum != PreviousService)
20296 if(ServiceAndRepeatNumTotal ==
"")
20298 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
20299 NumTrainsAtLoc = 1;
20303 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
20306 PreviousService = Ptr2->ServiceAndRepeatNum;
20307 if(ServiceAndRepeatNumTotal ==
"")
20309 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
20310 NumTrainsAtLoc = 1;
20314 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
20317 if(Ptr1->FrhMarker ==
"Frh")
20320 Ptr1->FrhMarker =
"FrhCounted";
20323 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
20327 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
20329 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
20331 AnsiString Asterisk =
"";
20332 if(NumTrainsAtLoc > NumPlats)
20339 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
20341 else if(FrhCount == 1)
20343 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
20347 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
20349 LastFrhCount = FrhCount;
20350 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
20351 AtLocsPrinted =
true;
20352 ServiceAndRepeatNumTotal =
"";
20355 if(Ptr2 == LocServiceTimesVector.end())
20359 if(Ptr2->Location != Ptr1->Location)
20364 if(Ptr2 == LocServiceTimesVector.end())
20372 TTFile3 <<
"Nothing to report for trains at locations";
20377 SequenceLog +=
"9\n";
20411 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
20416 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
20425 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
20427 SingleServiceEntry = TDE;
20429 for(
unsigned int y = 0; y < SSAV.size(); y++)
20431 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
20433 SingleServiceVector.push_back(SingleServiceEntry);
20436 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
20438 PartServiceEntry = TDE;
20440 for(
unsigned int z = 0; z <= y; z++)
20445 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
20446 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
20449 PartServiceVector.push_back(PartServiceEntry);
20450 if(SSAV.at(y).Command ==
"fsp")
20452 SSAV.at(y).Command =
"Front split - original service continues below";
20453 SSAV.at(y).OtherHeadCode =
"";
20455 if(SSAV.at(y).Command ==
"rsp")
20457 SSAV.at(y).Command =
"Rear split - original service continues below";
20458 SSAV.at(y).OtherHeadCode =
"";
20462 else if(SSAV.at(y).Command ==
"Fns")
20464 SSAV.at(y).Command =
"chr-Fns";
20465 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
20466 PartServiceVector.push_back(SingleServiceEntry);
20469 else if(SSAV.at(y).Command ==
"Fns-sh")
20471 SSAV.at(y).Command =
"chr-Fns-sh";
20472 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20473 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20474 PartServiceVector.push_back(SingleServiceEntry);
20477 else if(SSAV.at(y).Command ==
"F-nshs")
20479 SSAV.at(y).Command =
"chr-F-nshs";
20480 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
20481 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20482 PartServiceVector.push_back(SingleServiceEntry);
20488 SequenceLog +=
"10\n";
20492 AnsiString NextRef;
20493 while(!PartServiceVector.empty())
20495 PartServiceEntry = PartServiceVector.at(0);
20496 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
20498 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
20500 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
20504 bool FinishType =
true, FoundFlag =
false;
20511 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
20515 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20519 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20525 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20526 SingleServiceVector.push_back(PartServiceVector.at(0));
20527 PartServiceVector.erase(PartServiceVector.begin());
20532 NewPartServiceEntry = PartServiceVector.at(0);
20536 PartServiceVector.push_back(NewPartServiceEntry);
20539 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
20544 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
20547 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20549 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
20552 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
20554 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20557 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
20560 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20561 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20562 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20563 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20566 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
20570 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20571 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
20572 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20580 SequenceLog += +
"11\n";
20581 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
20585 if(!PartServiceVector.empty())
20587 SequenceLog +=
"12\n";
20588 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
20590 SequenceLog +=
"13\n";
20639 bool BufferFacingUnReportedFlag =
true;
20640 bool TrainFacingBuffersReported =
false;
20641 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20647 SequenceLog +=
"13a\n";
20648 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
20651 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
20653 bool BufferFlag =
false;
20654 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
20655 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
20656 AnsiString FrontLocName = AV.at(0).LocationName;
20657 int NextEntryPos, NextExitPos;
20660 if(ThisElement.
Conn[0] == RearTVPos)
20664 else if(ThisElement.
Conn[1] == RearTVPos)
20668 else if(ThisElement.
Conn[2] == RearTVPos)
20672 else if(ThisElement.
Conn[3] == RearTVPos)
20684 if(ThisElement.
Conn[ThisExitPos] == -1)
20686 SequenceLog =
"13b\n";
20687 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
20690 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
20691 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
20693 BufferFlag =
false;
20698 BufferFlag =
false;
20703 BufferFlag =
false;
20711 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
20713 ThisElement = NextElement;
20719 if(NextEntryPos == 0)
20723 else if(NextEntryPos == 1)
20727 else if(NextEntryPos == 2)
20731 else if(NextEntryPos == 3)
20736 ThisElement = NextElement;
20737 ThisExitPos = NextExitPos;
20742 if(BufferFacingUnReportedFlag)
20744 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
20745 BufferFacingUnReportedFlag =
false;
20747 if(AV.at(1).Command !=
"cdt")
20749 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
20750 TrainFacingBuffersReported =
true;
20755 if(!TrainFacingBuffersReported)
20757 TTFile3 <<
"Nothing to report for train facing directions\n\n";
20763 SequenceLog +=
"13c\n";
20766 AnsiString LocationNameToBeChecked =
"";
20767 bool MissingcdtUnreportedFlag =
true;
20769 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20772 unsigned int y = 0;
20773 int FirstInstance = 9999, SecondInstance = 9999;
20774 bool FullBreak =
false;
20775 MarkerList.clear();
20777 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
20786 LocationNameToBeChecked =
"";
20792 if(LocationNameToBeChecked ==
"")
20799 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
20802 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
20807 (AVEntry.
Command ==
"Frh-sh"))
20822 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
20824 AnsiString LocationName;
20831 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
20836 LocationName = TDEntry.
ActionVector.at(a).LocationName;
20838 if(LocationName == LocationNameToBeChecked)
20840 SecondInstance = a;
20842 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20844 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20846 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20849 if(MissingcdtUnreportedFlag)
20851 TTFile3 <<
"Possibly missing changes of direction - these should be checked to see if there is a good reason for cdt's not being included. :-\n\n";
20853 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
20854 MarkerList.push_back(FirstInstance);
20855 MarkerList.push_back(SecondInstance);
20857 MissingcdtUnreportedFlag =
false;
20868 if(MissingcdtUnreportedFlag)
20870 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20876 SequenceLog +=
"14\n";
20885 typedef std::list<AnsiString> TLocList;
20886 TLocList BackwardList, ForwardList;
20887 bool IntroLineNeeded =
true;
20888 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20890 unsigned int cdtPosition = 9999;
20891 AnsiString cdtLocation =
"";
20892 bool FoundSameName =
false;
20893 bool FerEntry =
false;
20894 MarkerList.clear();
20896 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
20903 BackwardList.clear();
20904 ForwardList.clear();
20905 bool ValidEnd =
false;
20911 (AVEntry.
Command ==
"Frh-sh"))
20916 if(FerEntry || ValidEnd)
20918 if(MarkerList.empty())
20925 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20927 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20929 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20933 if(IntroLineNeeded)
20935 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20936 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20937 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20938 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20939 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20940 IntroLineNeeded =
false;
20942 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20957 for(
int z = y - 1; z >= 0; z--)
20960 if(AVEntry2.
Command ==
"cdt")
20964 AnsiString LocName =
"";
20974 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
20976 BackwardList.push_back(LocName);
20979 BackwardList.sort();
20980 BackwardList.unique();
20981 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20990 AnsiString LocName =
"";
20991 if(AVEntry3.
Command ==
"Fer")
20993 int ExitLoc = AVEntry3.
ExitList.front();
21001 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
21003 ForwardList.push_back(LocName);
21006 ForwardList.sort();
21007 ForwardList.unique();
21008 FoundSameName =
false;
21010 if(!BackwardList.empty() && !ForwardList.empty())
21012 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
21014 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
21018 FoundSameName =
true;
21025 MarkerList.push_back(cdtPosition);
21030 if(IntroLineNeeded)
21032 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
21050 SequenceLog +=
"15\n";
21056 catch(
const Exception &e)
21058 AnsiString TTErrorFileName =
"Analysis Error.txt";
21059 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
21060 std::ofstream TTError(TTErrorFileName.c_str());
21063 ShowMessage(
"Analysis error file failed to open - can't be created");
21067 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
21068 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
21069 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
21072 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
21082 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
21084 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
21086 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
21088 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
21089 AnsiString Marker =
"";
21090 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
21093 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
21095 if(
int(x) == *MLIt)
21125 if(AVE.
Command.SubString(1,3) ==
"chr")
21134 AVE.
Command =
"Change of service to ";
21136 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
21138 AVE.
Command =
"Change to shuttle finishing service";
21140 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
21167 AnsiString ListOfExits =
"";
21176 VecFile << Marker <<
"Frh" <<
'\n';
21191 for(
unsigned int x = 0; x < Vector.size(); x++)
21194 if(Vector.at(x).ServiceReference == HeadCode)
21196 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
21198 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
21201 FinishType =
false;
21206 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
21209 FinishType =
false;
21214 return(Vector.at(x));
21218 return(Vector.at(Vector.size() - 1));
21227 if((Time1 ==
"") || (Time2 ==
""))
21232 int Mins = Time1.SubString(4,2).ToInt();
21233 int Hours = Time1.SubString(1,2).ToInt();
21234 int Time1Mins = (Hours * 60) + Mins;
21235 Mins = Time2.SubString(4,2).ToInt();
21236 Hours = Time2.SubString(1,2).ToInt();
21237 int Time2Mins = (Hours * 60) + Mins;
21238 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
21250 bool &AnalysisError,
int &MaxNumberOfSameDirections)
21257 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
21259 std::list<AnsiString> ServiceList;
21261 bool EvenComma =
false;
21262 for(
int x = 1; x <= Input.Length(); x++)
21264 TempStr1 = Input[x];
21265 if(TempStr1 == AnsiString(
',') && EvenComma)
21271 TempStr2 += Input[x];
21273 if(TempStr1 == AnsiString(
','))
21275 EvenComma = !EvenComma;
21279 while(TempStr2.Length() > 0)
21281 SCPos = TempStr2.Pos(
';');
21284 OneService = TempStr2.SubString(1, SCPos - 1);
21285 ServiceList.push_back(OneService);
21286 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
21290 ServiceList.push_back(TempStr2);
21294 ServiceList.sort();
21295 ServiceList.unique();
21296 NumTrainsAtLoc = ServiceList.size();
21299 int DirectionMarker = 0;
21301 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
21303 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21305 *SLIt = *SLIt +
"&0";
21307 SLIt3 = ServiceList.end();
21309 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
21310 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
21311 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
21313 MaxNumberOfSameDirections = 0;
21314 int SameDirectionCount = 0;
21316 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
21320 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
21326 CommaPos1 = SLIt1->Pos(
',');
21327 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
21329 SpacePos = ServiceRef1.Pos(
' ');
21333 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
21334 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
21335 if(RepeatInfo1[1] ==
'F')
21341 SpacePos = RepeatInfo1.Pos(
' ');
21342 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
21345 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
21347 AmpersandPos = AnsiTime1.Pos(
'&');
21348 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
21353 throw Exception(
"ASCLIt1 Error in " + Input);
21355 ServiceCallingLocsList1 = ASCLIt1->second;
21356 AmpersandPos = SLIt1->Pos(
'&');
21357 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
21358 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
21360 SameDirectionCount = 1;
21361 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
21363 CommaPos2 = SLIt2->Pos(
',');
21364 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
21366 SpacePos = ServiceRef2.Pos(
' ');
21370 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
21371 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
21372 if(RepeatInfo2[1] ==
'F')
21378 SpacePos = RepeatInfo2.Pos(
' ');
21379 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
21382 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
21384 AmpersandPos = AnsiTime2.Pos(
'&');
21385 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
21390 throw Exception(
"ASCLIt2 Error in " + Input);
21392 ServiceCallingLocsList2 = ASCLIt2->second;
21394 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
21396 int AmpersandPos = SLIt2->Pos(
'&');
21397 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
21398 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
21399 SameDirectionCount++;
21402 if(SameDirectionCount > MaxNumberOfSameDirections)
21404 MaxNumberOfSameDirections = SameDirectionCount;
21409 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
21412 AmpersandPos = SLIt3->Pos(
'&');
21413 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
21414 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
21417 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21420 AmpersandPos = SLIt->Pos(
'&');
21421 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
21422 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
21423 DirectionMarker = DirectionMarkerString.ToInt();
21424 AnsiString DirectionSuffix =
"";
21426 if(DirectionMarker < 27)
21428 c = 64 + DirectionMarker;
21429 DirectionSuffix =
"," + AnsiString(c);
21431 else if(DirectionMarker < 53)
21433 c = 65 + DirectionMarker - 27;
21434 DirectionSuffix =
",A" + AnsiString(c);
21438 DirectionSuffix =
",?";
21440 *SLIt = ServiceWithoutMarker + DirectionSuffix;
21443 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21445 Output = Output + *SLIt +
",";
21447 if(Output.Length() > 0)
21449 Output = Output.SubString(1, Output.Length() - 1);
21455 catch(
const Exception &e)
21457 AnalysisError =
true;
21469 AnsiString InternalInput = Input, Output =
"", OneService =
"";
21471 std::list<AnsiString> ServiceList;
21473 while(InternalInput.Length() > 0)
21475 CommaPos = InternalInput.Pos(
',');
21478 OneService = InternalInput.SubString(1, CommaPos - 1);
21479 ServiceList.push_back(OneService);
21480 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
21484 ServiceList.push_back(InternalInput);
21485 InternalInput =
"";
21489 ServiceList.sort();
21490 ServiceList.unique();
21491 NumTrainsAtLoc = ServiceList.size();
21492 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21494 Output = Output + *SLIt +
",";
21496 if(Output.Length() > 0)
21498 Output = Output.SubString(1, Output.Length() - 1);
21511 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
21513 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
21518 bool LocFound =
false;
21519 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
21521 TDateTime FirstServiceTime;
21524 int Ref1Target = 0, Ref1Count = 0;
21525 int Ref2Target = 0, Ref2Count = 0;
21543 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
21546 if((*ListPtr1) == Location)
21548 LocPtr1 = ListPtr1;
21551 if(ListPtr1->SubString(1, 3) ==
"%%%")
21553 AnsiString CDTTime = ListPtr1->SubString(4, 5);
21558 FirstServiceTime = TDateTime(-1);
21559 bool BreakFlag =
false;
21562 if(TDVIt->ServiceReference == Ref1)
21564 if(Ref1Target > Ref1Count)
21569 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
21570 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
21574 FirstServiceTime = AVIt->EventTime;
21580 FirstServiceTime = AVIt->ArrivalTime;
21586 FirstServiceTime = AVIt->DepartureTime;
21597 if(IncMinutes == -1)
21599 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21601 if(FirstServiceTime == TDateTime(-1))
21603 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21607 if(!Arrival && (Time1 == CDTTime))
21612 if(Arrival && (Time1 == CDTTime))
21616 if(Time1 > CDTTime)
21621 if(Time1 < CDTTime)
21634 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
21636 if((*ListPtr2) == Location)
21638 LocPtr2 = ListPtr2;
21641 if(ListPtr2->SubString(1, 3) ==
"%%%")
21643 AnsiString CDTTime = ListPtr2->SubString(4, 5);
21648 FirstServiceTime = TDateTime(-1);
21649 bool BreakFlag =
false;
21652 if(TDVIt->ServiceReference == Ref2)
21654 if(Ref2Target > Ref2Count)
21659 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
21660 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
21664 FirstServiceTime = AVIt->EventTime;
21670 FirstServiceTime = AVIt->ArrivalTime;
21676 FirstServiceTime = AVIt->DepartureTime;
21687 if(IncMinutes == -1)
21689 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21691 if(FirstServiceTime == TDateTime(-1))
21693 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21697 if(!Arrival && (Time2 == CDTTime))
21702 if(Arrival && (Time2 == CDTTime))
21706 if(Time2 > CDTTime)
21711 if(Time2 < CDTTime)
21726 LP1 = List1.begin();
21728 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
21730 if(ListPtr1 == List1.begin())
21734 if(ListPtr1->SubString(1, 3) ==
"%%%")
21741 LP2 = List2.begin();
21743 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
21745 if(ListPtr2 == List2.begin())
21749 if(ListPtr2->SubString(1, 3) ==
"%%%")
21759 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
21761 if(ListPtr1 == LocPtr1)
21765 if(ListPtr1->SubString(1, 3) ==
"%%%")
21769 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
21771 if(ListPtr2 == LocPtr2)
21775 if(ListPtr2->SubString(1, 3) ==
"%%%")
21779 if((*ListPtr1) == (*ListPtr2))
21796 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
21798 if(ListPtr1 == List1.end())
21802 if(ListPtr1->SubString(1, 3) ==
"%%%")
21806 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
21808 if(ListPtr2 == List2.end())
21812 if(ListPtr2->SubString(1, 3) ==
"%%%")
21816 if((*ListPtr1) == (*ListPtr2))
21833 if(ExitList.empty())
21839 AnsiString ExitLocList =
"";
21842 unsigned int Counter = 0;
21843 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
21847 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
21849 ExitLocList +=
"\n";
21852 if(StartName ==
"")
21854 if(ExitList.size() == 1)
21858 return(
" at " + ID);
21863 if(ExitList.size() < 4)
21865 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21870 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21875 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21880 if(ExitList.size() < 4)
21882 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21887 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21893 if(ExitList.size() < 4)
21895 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21896 return(
" at " + StartName);
21900 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21901 return(
" at " + StartName);
21941 AnsiString FormatStr =
"####0.0";
21942 AnsiString AvLateArrMins =
"";
21943 AnsiString AvEarlyArrMins =
"";
21944 AnsiString AvLatePassMins =
"";
21945 AnsiString AvEarlyPassMins =
"";
21946 AnsiString AvLateDepMins =
"";
21947 AnsiString AvLateExitMins =
"";
21948 AnsiString AvEarlyExitMins =
"";
21951 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21984 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21985 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21997 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
22001 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
22009 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
22013 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
22021 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
22029 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
22033 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
22037 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
22041 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
22045 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
22049 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
22054 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
22058 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
22062 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
22066 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
22070 PerfFile <<
LateExits <<
" late exits" <<
'\n';
22074 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
22078 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
22082 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
22087 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
22091 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
22095 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
22099 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
22103 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
22105 TDateTime TempExcessLCDownTime;
22119 if(TempExcessLCDownTime > TDateTime(0))
22125 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
22129 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
22141 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
22145 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
22181 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
22185 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
22191 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
22195 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
22198 AnsiString AvLateMinsLocsNotReached =
"";
22204 if(LocsNotReached > 0)
22207 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
22211 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
22215 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
22227 PerfFile <<
Derailments <<
" derailments" <<
'\n';
22231 PerfFile <<
Derailments <<
" derailment" <<
'\n';
22241 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
22243 bool DerailSPADFlag =
false, CrashFlag =
false;
22245 int OverallScorePercent = 100;
22246 int TotArrDepExit = 0;
22247 double TotLateMinsFactor = 1;
22248 double MissedStopAndSPADRiskFactor = 1;
22249 double NetNegFactor = 1;
22259 OverallScorePercent = 5;
22260 DerailSPADFlag =
true;
22264 OverallScorePercent = 0;
22267 if(OverallScorePercent == 100)
22272 LatenessPenalty = 0;
22278 if(TotArrDepExit > 0)
22287 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
22289 OverallScorePercent = 100 * NetNegFactor;
22292 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
22295 AnsiString OneFailureString =
", though the failure would account for some poor performance";
22296 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
22297 AnsiString AddedString =
"";
22300 AddedString = OneFailureString;
22304 AddedString = TwoOrMoreFailureString;
22306 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
22307 AnsiString Rating =
"";
22308 if(OverallScorePercent == 100)
22310 Rating =
"Perfect!";
22312 else if(OverallScorePercent >= 95)
22314 Rating =
"Excellent";
22316 else if(OverallScorePercent >= 90)
22318 Rating =
"Very good";
22320 else if(OverallScorePercent >= 80)
22324 else if(OverallScorePercent >= 70)
22328 else if(OverallScorePercent >= 60)
22330 Rating =
"Unacceptable" + AddedString;
22332 else if(OverallScorePercent >= 50)
22334 Rating =
"Poor" + AddedString;
22336 else if(OverallScorePercent >= 40)
22338 Rating =
"Bad" + AddedString;
22340 else if(OverallScorePercent >= 30)
22342 Rating =
"Very bad" + AddedString;
22344 else if(OverallScorePercent >= 20)
22346 Rating =
"Terrible" + AddedString;
22348 else if(OverallScorePercent >= 10)
22350 Rating =
"Appalling" + AddedString;
22352 else if(OverallScorePercent >= 5)
22356 Rating =
"Disastrous - potential loss of life";
22361 Rating =
"Dire" + AddedString;
22364 else if(OverallScorePercent < 5)
22368 Rating =
"Catastrophic - loss of life";
22372 Rating =
"Abysmal";
22375 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
22379 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
22381 PerfFile <<
'\n' <<
"***************************************";
22391 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22441 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22476 int IncrementalMinutes = 0;
22490 bool TrainOperatingFlag =
false;
22495 TrainOperatingFlag =
true;
22499 if(TrainOperatingFlag)
22507 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
22554 AnsiString HeadCode;
22558 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22562 HCandTrainPosParam.first = HeadCode;
22563 HCandTrainPosParam.second = TrainID;
22565 if((TimeToAct >= 0) && (TimeToAct < 59.9))
22568 OpTimeToActMultiMapEntry.first = TimeToAct;
22569 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
22598 float TimeToAct = 0;
22599 int DistanceToRedSignal = 0;
22602 ContinuationEntryVecPosVector.clear();
22603 bool LaterTrain =
false;
22607 LaterTrain =
false;
22608 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
22619 if(!ContinuationEntryVecPosVector.empty())
22621 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
22623 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
22637 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
22638 AnsiString HeadCode = CTEIt->second.HeadCode;
22639 float CurrentStopTime;
22640 float LaterStopTime;
22641 float RecoverableTime;
22644 int DistanceToExit;
22646 bool SigControlAndCanPassRedSignal =
false;
22654 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
22660 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
22661 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
22664 if(AvTrackSpeed < 30)
22668 if(DistanceToRedSignal == -1)
22674 int Speed = AvTrackSpeed;
22675 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
22676 if(AvTrackSpeed > MaxSpeed)
22680 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
22683 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
22686 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
22691 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
22692 TimeToAct += MinsBefEnter;
22695 HCandTrainPosParam.first = HeadCode;
22696 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
22699 if(TimeToAct < 59.9)
22701 OpTimeToActMultiMapEntry.first = TimeToAct;
22702 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
22727 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22737 TimeToExitMultiMapEntry.first = ExitPair;
22738 TimeToExitMultiMapEntry.second = ExitInfo;
22748 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
22749 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
22758 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
22759 int DistanceToRedSignal = 0;
22760 DistanceToExit = -1;
22761 ExitPair.first = -1;
22762 ExitPair.second = -1;
22763 int CumTrackSpeed = 0;
22765 int TrackSpeedCount = 0;
22766 float KmPerLocationStop;
22767 float MaxAllowableSpeed;
22777 int CurrentElement = TrackVectorPosition;
22778 int CurrentEntryPos = TrackVectorPositionEntryPos;
22783 CurrentStopTime = 0;
22785 RecoverableTime = 0;
22786 if(CurrentElement == -1)
22791 int CurrentExitPos;
22796 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
22800 CurrentExitPos = 1;
22804 CurrentExitPos = 3;
22809 CurrentExitPos = 0;
22849 TimeToDepart+= 0.5;
22851 if(TimeToDepart < 0.5)
22853 TimeToDepart = 0.5;
22856 CurrentStopTime = float(TimeToDepart);
22864 CurrentStopTime = float(TimeToDepart);
22875 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22886 else if(SigControlAndCanPassRedSignal)
22891 if((NextEntryPos == 0) || (NextEntryPos == 2))
22912 CurrentElement = NextElement;
22913 CurrentEntryPos = NextEntryPos;
22914 CurrentExitPos = NextExitPos;
22926 int LaterStopNumber = 0;
22930 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22939 if(CurrentEntryPos > 1)
22954 DistanceToExit = DistanceToRedSignal;
22959 if(TrackSpeedCount > 0)
22961 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22965 if(CurrentEntryPos > 1)
22976 if(LaterStopNumber > 0)
22978 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22979 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22985 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22989 if(AvTrackSpeed > MaxAllowableSpeed)
22991 AvTrackSpeed = MaxAllowableSpeed;
23003 bool StopRequired =
false;
23022 int TrainOnElement;
23029 if(CurrentEntryPos > 1)
23038 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
23047 double StopTimeDouble;
23060 if(StopTimeDouble < 0.5)
23062 StopTimeDouble = 0.5;
23066 LaterStopTime += float(StopTimeDouble);
23067 RecoverableTime += StopTimeDouble - 0.5;
23068 if((LaterStopNumber == 1) && (TrainID > -1))
23076 if((AVPtr + 1)->FormatType ==
TimeLoc)
23080 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
23091 if(StopTimeDouble < 0.5)
23093 StopTimeDouble = 0.5;
23096 LaterStopTime += float(StopTimeDouble);
23097 RecoverableTime += StopTimeDouble - 0.5;
23098 if((LaterStopNumber == 1) && (TrainID > -1))
23108 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
23119 if(StopTimeDouble < 0.5)
23121 StopTimeDouble = 0.5;
23124 LaterStopTime += float(StopTimeDouble);
23125 RecoverableTime += StopTimeDouble - 0.5;
23126 if((LaterStopNumber == 1) && (TrainID > -1))
23143 if(NextElement == -1)
23152 if((NextEntryPos == 0) || (NextEntryPos == 2))
23173 CurrentElement = NextElement;
23174 CurrentEntryPos = NextEntryPos;
23175 CurrentExitPos = NextExitPos;
23180 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
23193 if(TrackSpeedCount > 0)
23195 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
23199 if(CurrentEntryPos > 1)
23210 if(LaterStopNumber > 0)
23212 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
23213 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
23219 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
23223 if(AvTrackSpeed > MaxAllowableSpeed)
23225 AvTrackSpeed = MaxAllowableSpeed;
23228 return(DistanceToRedSignal);